diff --git a/src/checkbufferoverrun.cpp b/src/checkbufferoverrun.cpp index a36cc30b6..a532bb3d3 100644 --- a/src/checkbufferoverrun.cpp +++ b/src/checkbufferoverrun.cpp @@ -555,73 +555,10 @@ void CheckBufferOverrunClass::CheckBufferOverrun_StructVariable() } //--------------------------------------------------------------------------- -void CheckBufferOverrunClass::STLSizeProblems() -{ - for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) - { - if (!Token::simpleMatch(tok, "for (")) - continue; - - - int indent = 1; - tok = tok->tokAt(2); - const Token *num = 0; - const Token *var = 0; - while (tok) - { - - if (tok->str() == "(") - ++indent; - if (tok->str() == ")") - { - --indent; - if (indent == 0) - break; - } - - if (Token::Match(tok, "; %var% <= %var% . size ( ) ;")) - { - num = tok->tokAt(1); - var = tok->tokAt(3); - } - - tok = tok->next(); - } - - tok = tok->next(); - if (!num || tok->str() != "{") - continue; - - std::string pattern = var->str() + " [ " + num->str() + " ]"; - while (tok) - { - - if (tok->str() == "{") - ++indent; - if (tok->str() == "}") - { - --indent; - if (indent == 0) - break; - } - - - if (Token::Match(tok, pattern.c_str())) - { - _errorLogger->stlOutOfBounds(_tokenizer, tok, "When " + num->str() + " == size(), " + pattern); - } - - tok = tok->next(); - } - } - -} - void CheckBufferOverrunClass::bufferOverrun() { CheckBufferOverrun_LocalVariable(); CheckBufferOverrun_StructVariable(); - STLSizeProblems(); } //--------------------------------------------------------------------------- diff --git a/src/checkbufferoverrun.h b/src/checkbufferoverrun.h index 5a9890c92..e652e5cfd 100644 --- a/src/checkbufferoverrun.h +++ b/src/checkbufferoverrun.h @@ -45,12 +45,6 @@ private: /** Check for buffer overruns - this is the function that performs the actual checking */ void CheckBufferOverrun_CheckScope(const Token *tok, const char *varname[], const int size, const int total_size, unsigned int varid); - /** - * Finds errors like this: - * for (unsigned ii = 0; ii <= foo.size(); ++ii) - */ - void STLSizeProblems(); - const Tokenizer *_tokenizer; const Settings _settings; ErrorLogger *_errorLogger; diff --git a/src/checkstl.cpp b/src/checkstl.cpp index 600e61525..8b5882800 100644 --- a/src/checkstl.cpp +++ b/src/checkstl.cpp @@ -47,3 +47,66 @@ void CheckStl::iterators() } } } + + +void CheckStl::stlOutOfBounds() +{ + for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) + { + if (!Token::simpleMatch(tok, "for (")) + continue; + + + int indent = 1; + tok = tok->tokAt(2); + const Token *num = 0; + const Token *var = 0; + while (tok) + { + + if (tok->str() == "(") + ++indent; + if (tok->str() == ")") + { + --indent; + if (indent == 0) + break; + } + + if (Token::Match(tok, "; %var% <= %var% . size ( ) ;")) + { + num = tok->tokAt(1); + var = tok->tokAt(3); + } + + tok = tok->next(); + } + + tok = tok->next(); + if (!num || tok->str() != "{") + continue; + + std::string pattern = var->str() + " [ " + num->str() + " ]"; + while (tok) + { + + if (tok->str() == "{") + ++indent; + if (tok->str() == "}") + { + --indent; + if (indent == 0) + break; + } + + + if (Token::Match(tok, pattern.c_str())) + { + _errorLogger->stlOutOfBounds(_tokenizer, tok, "When " + num->str() + " == size(), " + pattern); + } + + tok = tok->next(); + } + } + +} diff --git a/src/checkstl.h b/src/checkstl.h index 38b464930..141502f8f 100644 --- a/src/checkstl.h +++ b/src/checkstl.h @@ -32,6 +32,13 @@ public: CheckStl(const Tokenizer *tokenizer, ErrorLogger *errorLogger); ~CheckStl(); + + /** + * Finds errors like this: + * for (unsigned ii = 0; ii <= foo.size(); ++ii) + */ + void stlOutOfBounds(); + void iterators(); private: diff --git a/src/cppcheck.cpp b/src/cppcheck.cpp index cc88c2949..7ed274988 100644 --- a/src/cppcheck.cpp +++ b/src/cppcheck.cpp @@ -412,6 +412,9 @@ void CppCheck::checkFile(const std::string &code, const char FileName[]) CheckStl checkStl(&_tokenizer, this); if (ErrorLogger::iteratorUsage()) checkStl.iterators(); + + if (ErrorLogger::stlOutOfBounds()) + checkStl.stlOutOfBounds(); } Settings CppCheck::settings() const diff --git a/test/testbufferoverrun.cpp b/test/testbufferoverrun.cpp index 1c8913b1f..e9ce1f494 100644 --- a/test/testbufferoverrun.cpp +++ b/test/testbufferoverrun.cpp @@ -93,8 +93,6 @@ private: TEST_CASE(varid1); TEST_CASE(varid2); - TEST_CASE(STLSize); - TEST_CASE(STLSizeNoErr); } @@ -472,45 +470,6 @@ private: "}\n"); ASSERT_EQUALS(std::string(""), errout.str()); } - - void STLSize() - { - check("void foo()\n" - "{\n" - " std::vector foo;\n" - " for (unsigned int ii = 0; ii <= foo.size(); ++ii)\n" - " {\n" - " foo[ii] = 0;\n" - " }\n" - "}\n"); - ASSERT_EQUALS(std::string("[test.cpp:6]: (error) When ii == size(), foo [ ii ] is out of bounds\n"), errout.str()); - } - - void STLSizeNoErr() - { - { - check("void foo()\n" - "{\n" - " std::vector foo;\n" - " for (unsigned int ii = 0; ii < foo.size(); ++ii)\n" - " {\n" - " foo[ii] = 0;\n" - " }\n" - "}\n"); - ASSERT_EQUALS(std::string(""), errout.str()); - } - - { - check("void foo()\n" - "{\n" - " std::vector foo;\n" - " for (unsigned int ii = 0; ii <= foo.size(); ++ii)\n" - " {\n" - " }\n" - "}\n"); - ASSERT_EQUALS(std::string(""), errout.str()); - } - } }; REGISTER_TEST(TestBufferOverrun) diff --git a/test/teststl.cpp b/test/teststl.cpp index 9fd5a2b50..435db8e47 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -37,6 +37,8 @@ private: void run() { TEST_CASE(iterator1); + TEST_CASE(STLSize); + TEST_CASE(STLSizeNoErr); } void check(const char code[]) @@ -52,6 +54,7 @@ private: // Check char variable usage.. CheckStl checkStl(&tokenizer, this); checkStl.iterators(); + checkStl.stlOutOfBounds(); } @@ -65,6 +68,45 @@ private: ASSERT_EQUALS("[test.cpp:3]: (error) Same iterator is used with both foo and bar\n", errout.str()); } + + void STLSize() + { + check("void foo()\n" + "{\n" + " std::vector foo;\n" + " for (unsigned int ii = 0; ii <= foo.size(); ++ii)\n" + " {\n" + " foo[ii] = 0;\n" + " }\n" + "}\n"); + ASSERT_EQUALS(std::string("[test.cpp:6]: (error) When ii == size(), foo [ ii ] is out of bounds\n"), errout.str()); + } + + void STLSizeNoErr() + { + { + check("void foo()\n" + "{\n" + " std::vector foo;\n" + " for (unsigned int ii = 0; ii < foo.size(); ++ii)\n" + " {\n" + " foo[ii] = 0;\n" + " }\n" + "}\n"); + ASSERT_EQUALS(std::string(""), errout.str()); + } + + { + check("void foo()\n" + "{\n" + " std::vector foo;\n" + " for (unsigned int ii = 0; ii <= foo.size(); ++ii)\n" + " {\n" + " }\n" + "}\n"); + ASSERT_EQUALS(std::string(""), errout.str()); + } + } }; REGISTER_TEST(TestStl)