From 5285635354713ba420a6a9803c1e8a11b88899ee Mon Sep 17 00:00:00 2001 From: Slava Semushin Date: Sun, 27 Sep 2009 14:59:19 +0700 Subject: [PATCH] Fixed #735 (Detects invalid iterator after push_back() when iterator declared inside for()) http://sourceforge.net/apps/trac/cppcheck/ticket/735 --- src/checkstl.cpp | 27 +++++++++++++++++++++++---- test/teststl.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/checkstl.cpp b/src/checkstl.cpp index e8bce38af..4ab3e5883 100644 --- a/src/checkstl.cpp +++ b/src/checkstl.cpp @@ -273,6 +273,14 @@ void CheckStl::pushback() { if (Token::simpleMatch(tok, "vector <")) { + // if iterator declaration inside for() loop + bool iteratorDeclaredInsideLoop = false; + if ((tok->tokAt(-2) && Token::simpleMatch(tok->tokAt(-2), "for (")) || + (tok->tokAt(-4) && Token::simpleMatch(tok->tokAt(-4), "for ( std ::"))) + { + iteratorDeclaredInsideLoop = true; + } + while (tok && tok->str() != ">") tok = tok->next(); if (!tok) @@ -283,6 +291,12 @@ void CheckStl::pushback() if (iteratorid == 0) continue; + if (iteratorDeclaredInsideLoop && tok->tokAt(4)->str() == "=") + { + // skip "> :: iterator|const_iterator" + tok = tok->tokAt(3); + } + std::string vectorname; int indent = 0; bool invalidIterator = false; @@ -299,15 +313,20 @@ void CheckStl::pushback() } // Using push_back or push_front inside a loop.. - if (Token::Match(tok2, "for ( %varid% = %var% . begin ( ) ; %varid% != %var% . end ( ) ; ++ %varid% ) {", iteratorid)) + if (Token::Match(tok2, "for (")) { - const unsigned int vectorid(tok2->tokAt(4)->varId()); + tok2 = tok2->tokAt(2); + } + + if (Token::Match(tok2, "%varid% = %var% . begin ( ) ; %varid% != %var% . end ( ) ; ++ %varid% ) {", iteratorid)) + { + const unsigned int vectorid(tok2->tokAt(2)->varId()); if (vectorid == 0) continue; const Token *pushback = 0; unsigned int indent3 = 0; - for (const Token *tok3 = tok2->tokAt(22); tok3; tok3 = tok3->next()) + for (const Token *tok3 = tok2->tokAt(20); tok3; tok3 = tok3->next()) { if (tok3->str() == "{") ++indent3; @@ -329,7 +348,7 @@ void CheckStl::pushback() } if (pushback) - pushbackError(pushback, tok2->strAt(2)); + pushbackError(pushback, tok2->strAt(0)); } // Assigning iterator.. diff --git a/test/teststl.cpp b/test/teststl.cpp index 33aaf3a51..211fc9773 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -56,6 +56,7 @@ private: TEST_CASE(pushback3); TEST_CASE(pushback4); TEST_CASE(pushback5); + TEST_CASE(pushback6); TEST_CASE(insert1); @@ -390,6 +391,35 @@ private: ASSERT_EQUALS("", errout.str()); } + void pushback6() + { + // ticket #735 + check("void f()\n" + "{\n" + " vector v;\n" + " vector.push_back(1);\n" + " vector.push_back(2);\n" + " for (vector::iterator it = v.begin(); it != v.end(); ++it)\n" + " {\n" + " if (*it == 1)\n" + " v.push_back(10);\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:9]: (error) After push_back or push_front, the iterator 'it' may be invalid\n", errout.str()); + + check("void f()\n" + "{\n" + " std::vector v;\n" + " vector.push_back(1);\n" + " vector.push_back(2);\n" + " for (std::vector::iterator it = v.begin(); it != v.end(); ++it)\n" + " {\n" + " if (*it == 1)\n" + " v.push_back(10);\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:9]: (error) After push_back or push_front, the iterator 'it' may be invalid\n", errout.str()); + } void insert1()