CheckBufferOverrun: Use AST to lookup array

This commit is contained in:
Daniel Marjamäki 2019-03-12 06:46:38 +01:00
parent 35bbe5617a
commit 0c08f6db6c
2 changed files with 21 additions and 11 deletions

View File

@ -176,29 +176,35 @@ static size_t getMinFormatStringOutputLength(const std::vector<const Token*> &pa
void CheckBufferOverrun::arrayIndex()
{
for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) {
if (!Token::Match(tok, "%name% [") || !tok->variable() || tok->variable()->nameToken() == tok)
if (tok->str() != "[")
continue;
if (!tok->scope()->isExecutable()) {
const Token *array = tok->astOperand1();
while (Token::Match(array, ".|::"))
array = array->astOperand2();
if (!array|| !array->variable() || array->variable()->nameToken() == array)
continue;
if (!array->scope()->isExecutable()) {
// LHS in non-executable scope => This is just a definition
const Token *parent = tok->next();
const Token *parent = tok;
while (parent && !Token::simpleMatch(parent->astParent(), "="))
parent = parent->astParent();
if (parent && parent == parent->astParent()->astOperand1())
continue;
}
const Token *indexToken = tok->next()->astOperand2();
const Token *indexToken = tok->astOperand2();
if (!indexToken)
continue;
const Token *stringLiteral = nullptr;
if (!tok->variable()->isArray() && tok->variable()->dimensions().empty()) {
stringLiteral = tok->getValueTokenMinStrSize();
if (!array->variable()->isArray() && array->variable()->dimensions().empty()) {
stringLiteral = array->getValueTokenMinStrSize();
if (!stringLiteral)
continue;
}
const MathLib::bigint dim = stringLiteral ? Token::getStrSize(stringLiteral) : tok->variable()->dimensions()[0].num;
const MathLib::bigint dim = stringLiteral ? Token::getStrSize(stringLiteral) : array->variable()->dimensions()[0].num;
// Positive index
if (stringLiteral || dim > 1) { // TODO check arrays with dim 1 also
@ -210,20 +216,20 @@ void CheckBufferOverrun::arrayIndex()
if (index < dim)
continue;
if (index == dim) {
const Token *parent = tok->next();
const Token *parent = tok;
while (Token::simpleMatch(parent, "["))
parent = parent->astParent();
if (parent->str() == "&")
if (parent->isUnaryOp("&"))
continue;
}
arrayIndexError(tok->next(), tok->variable(), value);
arrayIndexError(tok, array->variable(), value);
}
}
// Negative index
const ValueFlow::Value *negativeValue = indexToken->getValueLE(-1, mSettings);
if (negativeValue) {
negativeIndexError(tok->next(), tok->variable(), negativeValue);
negativeIndexError(tok, array->variable(), negativeValue);
}
}
}

View File

@ -358,6 +358,10 @@ private:
check("int x[5];\n"
"int a = x[10];\n");
ASSERT_EQUALS("[test.cpp:2]: (error) Array 'x[5]' accessed at index 10, which is out of bounds.\n", errout.str());
check("int x[5];\n"
"int a = (x)[10];\n");
ASSERT_EQUALS("[test.cpp:2]: (error) Array 'x[5]' accessed at index 10, which is out of bounds.\n", errout.str());
}