From df3ffa2eda4e49b8b3c45e77c4ccde92fa2d786c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 2 Nov 2009 20:24:38 +0100 Subject: [PATCH] STL: added check for dangerous usage of std::find (#829) --- lib/checkstl.cpp | 32 ++++++++++++++++++++++++++++++++ lib/checkstl.h | 9 ++++++++- test/teststl.cpp | 14 ++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index ddf2f697d..9cfe45a97 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -482,3 +482,35 @@ void CheckStl::stlBoundriesError(const Token *tok, const std::string &container_ { reportError(tok, Severity::error, "stlBoundries", container_name + " range check should use != and not < since the order of the pointers isn't guaranteed"); } + + + +void CheckStl::find() +{ + for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) + { + if (tok->str() != ";") + continue; + if (!Token::Match(tok->next(), "%var% = std :: find (")) + continue; + const unsigned int iteratorid = tok->next()->varId(); + if (iteratorid == 0) + continue; + tok = tok->tokAt(6)->link(); + if (!tok) + break; + for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) + { + if (tok2->str() == "{" || tok2->str() == "}" || tok2->str() == "(" || tok2->str() == ")") + break; + if (tok2->varId() == iteratorid && Token::simpleMatch(tok2->previous(), "*")) + findError(tok2); + } + } +} + + +void CheckStl::findError(const Token *tok) +{ + reportError(tok, Severity::error, "stlfind", "dangerous usage of find result"); +} diff --git a/lib/checkstl.h b/lib/checkstl.h index b5114ab51..11861be6d 100644 --- a/lib/checkstl.h +++ b/lib/checkstl.h @@ -53,6 +53,7 @@ public: checkStl.erase(); checkStl.pushback(); checkStl.stlBoundries(); + checkStl.find(); } @@ -91,6 +92,9 @@ public: * bad condition.. "it < alist.end()" */ void stlBoundries(); + + /** usage of std::find */ + void find(); private: @@ -108,6 +112,7 @@ private: void invalidIteratorError(const Token *tok, const std::string &func, const std::string &iterator_name); void invalidPointerError(const Token *tok, const std::string &pointer_name); void stlBoundriesError(const Token *tok, const std::string &container_name); + void findError(const Token *tok); void getErrorMessages() { @@ -119,6 +124,7 @@ private: invalidIteratorError(0, "push_back|push_front|insert", "iterator"); invalidPointerError(0, "pointer"); stlBoundriesError(0, "container"); + findError(0); } std::string name() const @@ -133,7 +139,8 @@ private: " * misuse of iterators when iterating through a container\n" " * mismatching containers in calls\n" " * dereferencing an erased iterator\n" - " * for vectors: using iterator/pointer after push_back has been used\n"; + " * for vectors: using iterator/pointer after push_back has been used\n" + " * dangerous usage of find"; } }; /// @} diff --git a/test/teststl.cpp b/test/teststl.cpp index 6f9aecf19..1bfb552ad 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -68,6 +68,9 @@ private: TEST_CASE(stlBoundries1); TEST_CASE(stlBoundries2); TEST_CASE(stlBoundries3); + + // find + TEST_CASE(find1); } void check(const char code[]) @@ -571,6 +574,17 @@ private: ASSERT_EQUALS("", errout.str()); } + + void find1() + { + check("void f(std::vector &ints)\n" + "{\n" + " std::vector::iterator it = std::find(ints.begin(), ints.end(), 33);\n" + " *it = 11;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } + }; REGISTER_TEST(TestStl)