diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index d126c4951..bbea60903 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -2101,10 +2101,15 @@ void CheckBufferOverrun::arrayIndexThenCheck() const Scope * const scope = symbolDatabase->functionScopes[i]; for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) { if (Token::Match(tok, "%var% [ %var% ]")) { - const std::string& indexName(tok->strAt(2)); + tok = tok->tokAt(2); + unsigned int indexID = tok->varId(); + if (!indexID) + continue; + + const std::string& indexName(tok->str()); // skip array index.. - tok = tok->tokAt(4); + tok = tok->tokAt(2); while (tok && tok->str() == "[") tok = tok->link()->next(); @@ -2117,13 +2122,14 @@ void CheckBufferOverrun::arrayIndexThenCheck() tok = tok->tokAt(2); // skip close parenthesis - if (tok->str() == ")") { + if (tok->str() == ")") tok = tok->next(); - } // check if array index is ok // statement can be closed in parentheses, so "(| " is using - if (Token::Match(tok, ("&& (| " + indexName + " <|<=").c_str())) + if (Token::Match(tok, "&& (| %varid% <|<=", indexID)) + arrayIndexThenCheckError(tok, indexName); + else if (Token::Match(tok, "&& (| %any% >|>= %varid%", indexID)) arrayIndexThenCheckError(tok, indexName); } } diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 061eaad96..94fc8a720 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -3950,10 +3950,16 @@ private: " if (s[i] == 'x' && i < y) {\n" " }" "}"); + ASSERT_EQUALS("", errout.str()); // No message because i is unknown and thus gets no varid. Avoid an internalError here. + + check("void f(const char s[], int i) {\n" + " if (s[i] == 'x' && i < y) {\n" + " }" + "}"); ASSERT_EQUALS("[test.cpp:2]: (style) Array index 'i' is used before limits check.\n", errout.str()); check("void f(const char s[]) {\n" - " for (i = 0; s[i] == 'x' && i < y; ++i) {\n" + " for (int i = 0; s[i] == 'x' && i < y; ++i) {\n" " }" "}"); ASSERT_EQUALS("[test.cpp:2]: (style) Array index 'i' is used before limits check.\n", errout.str()); @@ -3964,6 +3970,12 @@ private: "}"); ASSERT_EQUALS("[test.cpp:2]: (style) Array index 'i' is used before limits check.\n", errout.str()); + check("void f(const int a[], unsigned i) {\n" + " if((a[i] < 2) && (42 >= i)) {\n" + " }\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (style) Array index 'i' is used before limits check.\n", errout.str()); + // this one doesn't work for now, hopefully in the future check("void f(const int a[], unsigned i) {\n" " if(a[i] < func(i) && i <= 42) {\n"