Skip to content

Commit 171e1b8

Browse files
committed
Fixed false negatives in CheckBufferOverrun::arrayIndexThenCheck()
1 parent d54744b commit 171e1b8

2 files changed

Lines changed: 28 additions & 24 deletions

File tree

lib/checkbufferoverrun.cpp

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1864,35 +1864,28 @@ void CheckBufferOverrun::arrayIndexThenCheck()
18641864
}
18651865

18661866
if (Token::Match(tok, "%name% [ %var% ]")) {
1867-
tok = tok->tokAt(2);
1867+
tok = tok->next();
18681868

1869-
const unsigned int indexID = tok->varId();
1870-
const std::string& indexName(tok->str());
1869+
const unsigned int indexID = tok->next()->varId();
1870+
const std::string& indexName(tok->strAt(1));
18711871

1872-
// skip array index..
1873-
tok = tok->tokAt(2);
1874-
while (tok && tok->str() == "[")
1875-
tok = tok->link()->next();
1876-
1877-
// syntax error
1878-
if (!tok)
1879-
return;
1880-
1881-
// skip comparison
1882-
if (tok->tokType() == Token::eComparisonOp)
1883-
tok = tok->tokAt(2);
1872+
// Iterate AST upwards
1873+
const Token* tok2 = tok;
1874+
const Token* tok3 = tok2;
1875+
while (tok2->astParent() && tok2->tokType() != Token::eLogicalOp) {
1876+
tok3 = tok2;
1877+
tok2 = tok2->astParent();
1878+
}
18841879

1885-
if (!tok)
1886-
break;
1887-
// skip close parentheses
1888-
if (tok->str() == ")")
1889-
tok = tok->next();
1880+
// Ensure that we ended at a logical operator and that we came from its left side
1881+
if (tok2->tokType() != Token::eLogicalOp || tok2->astOperand1() != tok3)
1882+
continue;
18901883

18911884
// check if array index is ok
18921885
// statement can be closed in parentheses, so "(| " is using
1893-
if (Token::Match(tok, "&& (| %varid% <|<=", indexID))
1886+
if (Token::Match(tok2, "&& (| %varid% <|<=", indexID))
18941887
arrayIndexThenCheckError(tok, indexName);
1895-
else if (Token::Match(tok, "&& (| %any% >|>= %varid% !!+", indexID))
1888+
else if (Token::Match(tok2, "&& (| %any% >|>= %varid% !!+", indexID))
18961889
arrayIndexThenCheckError(tok, indexName);
18971890
}
18981891
}

test/testbufferoverrun.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3876,12 +3876,23 @@ class TestBufferOverrun : public TestFixture {
38763876
"}");
38773877
ASSERT_EQUALS("", errout.str());
38783878

3879-
// this one doesn't work for now, hopefully in the future
38803879
check("void f(const int a[], unsigned i) {\n"
38813880
" if(a[i] < func(i) && i <= 42) {\n"
38823881
" }\n"
38833882
"}");
3884-
TODO_ASSERT_EQUALS("[test.cpp:2]: (style) Array index 'i' is used before limits check.\n", "", errout.str());
3883+
ASSERT_EQUALS("[test.cpp:2]: (style) Array index 'i' is used before limits check.\n", errout.str());
3884+
3885+
check("void f(const int a[], unsigned i) {\n"
3886+
" if (i <= 42 && a[i] < func(i)) {\n"
3887+
" }\n"
3888+
"}");
3889+
ASSERT_EQUALS("", errout.str());
3890+
3891+
check("void f(const int a[], unsigned i) {\n"
3892+
" if (foo(a[i] + 3) < func(i) && i <= 42) {\n"
3893+
" }\n"
3894+
"}");
3895+
ASSERT_EQUALS("[test.cpp:2]: (style) Array index 'i' is used before limits check.\n", errout.str());
38853896

38863897
check("void f(int i) {\n" // sizeof
38873898
" sizeof(a)/sizeof(a[i]) && i < 10;\n"

0 commit comments

Comments
 (0)