diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index d8c427415..0d1986010 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -1633,122 +1633,6 @@ static bool hasArrayEndParen(const Token *tok1) //--------------------------------------------------------------------------- // //--------------------------------------------------------------------------- -void CheckStl::checkAutoPointer() -{ - std::set autoPtrVarId; - std::map mallocVarId; // variables allocated by the malloc-like function - const char STL_CONTAINER_LIST[] = "array|bitset|deque|list|forward_list|map|multimap|multiset|priority_queue|queue|set|stack|vector|hash_map|hash_multimap|hash_set|unordered_map|unordered_multimap|unordered_set|unordered_multiset|basic_string"; - const int malloc = mSettings->library.allocId("malloc"); // allocation function, which are not compatible with auto_ptr - const bool printStyle = mSettings->isEnabled(Settings::STYLE); - - for (const Token *tok = mTokenizer->tokens(); tok; tok = tok->next()) { - if (Token::simpleMatch(tok, "auto_ptr <")) { - if ((tok->strAt(-1) == "<" && Token::Match(tok->tokAt(-2), STL_CONTAINER_LIST)) || - (Token::simpleMatch(tok->tokAt(-3), "< std :: auto_ptr") && Token::Match(tok->tokAt(-4), STL_CONTAINER_LIST))) { - autoPointerContainerError(tok); - } else { - const Token *tok2 = tok->linkAt(1); - - if (Token::Match(tok2, "> %name%")) { - const Token *tok3 = tok2->tokAt(2); - if (Token::Match(tok3, "( new %type%") && hasArrayEndParen(tok3)) { - autoPointerArrayError(tok2->next()); - } - if (Token::Match(tok3, "( %name% (") && malloc && mSettings->library.alloc(tok3->next(), -1) == malloc) { - // malloc-like function allocated memory passed to the auto_ptr constructor -> error - autoPointerMallocError(tok2->next(), tok3->next()->str()); - } - if (Token::Match(tok3, "( %var%")) { - const std::map::const_iterator it = mallocVarId.find(tok3->next()->varId()); - if (it != mallocVarId.cend()) { - // pointer on the memory allocated by malloc used in the auto pointer constructor -> error - autoPointerMallocError(tok2->next(), it->second); - } - } - while (tok3 && tok3->str() != ";") { - tok3 = tok3->next(); - } - if (tok3) { - tok3 = tok3->tokAt(-2); - if (Token::simpleMatch(tok3->previous(), "[ ] )")) { - autoPointerArrayError(tok2->next()); - } else if (tok3->varId()) { - const Token *decltok = Token::findmatch(mTokenizer->tokens(), "%varid% = new %type%", tok3->varId()); - if (decltok && hasArrayEnd(decltok)) { - autoPointerArrayError(tok2->next()); - } - } - if (tok2->next()->varId()) { - autoPtrVarId.insert(tok2->next()->varId()); - } - } - } - } - } else { - if (Token::Match(tok, "%name% = %var% ;")) { - if (printStyle) { - const std::set::const_iterator iter = autoPtrVarId.find(tok->tokAt(2)->varId()); - if (iter != autoPtrVarId.end()) { - autoPointerError(tok->tokAt(2)); - } - } - } else if ((Token::Match(tok, "%var% = new %type%") && hasArrayEnd(tok)) || - (Token::Match(tok, "%var% . reset ( new %type%") && hasArrayEndParen(tok))) { - const std::set::const_iterator iter = autoPtrVarId.find(tok->varId()); - if (iter != autoPtrVarId.end()) { - autoPointerArrayError(tok); - } - } else if (Token::Match(tok, "%var% = %name% (") && malloc && mSettings->library.alloc(tok->tokAt(2), -1) == malloc) { - // C library function like 'malloc' used together with auto pointer -> error - const std::set::const_iterator iter = autoPtrVarId.find(tok->varId()); - if (iter != autoPtrVarId.end()) { - autoPointerMallocError(tok, tok->strAt(2)); - } else if (tok->varId()) { - // it is not an auto pointer variable and it is allocated by malloc like function. - mallocVarId.insert(std::make_pair(tok->varId(), tok->strAt(2))); - } - } else if (Token::Match(tok, "%var% . reset ( %name% (") && malloc && mSettings->library.alloc(tok->tokAt(4), -1) == malloc) { - // C library function like 'malloc' used when resetting auto pointer -> error - const std::set::const_iterator iter = autoPtrVarId.find(tok->varId()); - if (iter != autoPtrVarId.end()) { - autoPointerMallocError(tok, tok->strAt(4)); - } - } - } - } -} - - -void CheckStl::autoPointerError(const Token *tok) -{ - reportError(tok, Severity::style, "useAutoPointerCopy", - "Copying 'auto_ptr' pointer to another does not create two equal objects since one has lost its ownership of the pointer.\n" - "'std::auto_ptr' has semantics of strict ownership, meaning that the 'auto_ptr' instance is the sole entity responsible for the object's lifetime. If an 'auto_ptr' is copied, the source looses the reference.", - CWE398, false); -} - -void CheckStl::autoPointerContainerError(const Token *tok) -{ - reportError(tok, Severity::error, "useAutoPointerContainer", - "You can randomly lose access to pointers if you store 'auto_ptr' pointers in an STL container.\n" - "An element of container must be able to be copied but 'auto_ptr' does not fulfill this requirement. You should consider to use 'shared_ptr' or 'unique_ptr'. It is suitable for use in containers, because they no longer copy their values, they move them.", CWE664, false - ); -} - -void CheckStl::autoPointerArrayError(const Token *tok) -{ - reportError(tok, Severity::error, "useAutoPointerArray", - "Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n" - "Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. This means that you should only use 'auto_ptr' for pointers obtained with operator 'new'. This excludes arrays, which are allocated by operator 'new[]' and must be deallocated by operator 'delete[]'.", CWE664, false - ); -} - -void CheckStl::autoPointerMallocError(const Token *tok, const std::string& allocFunction) -{ - const std::string summary = "Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function '$symbol'."; - const std::string verbose = summary + " This means that you should only use 'auto_ptr' for pointers obtained with operator 'new'. This excludes use C library allocation functions (for example '$symbol'), which must be deallocated by the appropriate C library function."; - reportError(tok, Severity::error, "useAutoPointerMalloc", "$symbol:" + allocFunction + '\n' + summary + '\n' + verbose, CWE762, false); -} namespace { const std::set stl_containers_with_empty_and_clear = { diff --git a/lib/checkstl.h b/lib/checkstl.h index 53d8ac890..a8383e59e 100644 --- a/lib/checkstl.h +++ b/lib/checkstl.h @@ -83,7 +83,6 @@ public: checkStl.stlOutOfBounds(); checkStl.negativeIndex(); checkStl.stlBoundaries(); - checkStl.checkAutoPointer(); checkStl.checkDereferenceInvalidIterator(); // Style check @@ -164,9 +163,6 @@ public: /** Check for common mistakes when using the function string::c_str() */ void string_c_str(); - /** @brief %Check for use and copy auto pointer */ - void checkAutoPointer(); - /** @brief %Check calls that using them is useless */ void uselessCalls(); @@ -218,11 +214,6 @@ private: void sizeError(const Token* tok); void redundantIfRemoveError(const Token* tok); - void autoPointerError(const Token* tok); - void autoPointerContainerError(const Token* tok); - void autoPointerArrayError(const Token* tok); - void autoPointerMallocError(const Token* tok, const std::string& allocFunction); - void uselessCallsReturnValueError(const Token* tok, const std::string& varname, const std::string& function); void uselessCallsSwapError(const Token* tok, const std::string& varname); void uselessCallsSubstrError(const Token* tok, bool empty); @@ -264,10 +255,6 @@ private: c.sizeError(nullptr); c.missingComparisonError(nullptr, nullptr); c.redundantIfRemoveError(nullptr); - c.autoPointerError(nullptr); - c.autoPointerContainerError(nullptr); - c.autoPointerArrayError(nullptr); - c.autoPointerMallocError(nullptr, "malloc"); c.uselessCallsReturnValueError(nullptr, "str", "find"); c.uselessCallsSwapError(nullptr, "str"); c.uselessCallsSubstrError(nullptr, false); @@ -294,7 +281,6 @@ private: "- suspicious condition when using find\n" "- redundant condition\n" "- common mistakes when using string::c_str()\n" - "- using auto pointer (auto_ptr)\n" "- useless calls of string and STL functions\n" "- dereferencing an invalid iterator\n" "- reading from empty STL container\n" diff --git a/test/teststl.cpp b/test/teststl.cpp index 0e8c5ac53..8e126cafb 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -143,8 +143,6 @@ private: // catch common problems when using the string::c_str() function TEST_CASE(cstr); - TEST_CASE(autoPointer); - TEST_CASE(uselessCalls); TEST_CASE(stabilityOfChecks); // #4684 cppcheck crash in template function call @@ -3056,205 +3054,6 @@ private: ASSERT_EQUALS("[test.cpp:7]: (error) Dangerous usage of c_str(). The value returned by c_str() is invalid after this call.\n", errout.str()); } - void autoPointer() { - - // ticket 2846 - check("void f()\n" - "{\n" - " std::vector vec;\n" - " vec.push_back(new int(3));\n" - " std::auto_ptr ret(vec[0]);\n" - "};"); - ASSERT_EQUALS("", errout.str()); - - // ticket 2839 - check("template \n" - "class Guarded\n" - "{\n" - " typedef std::auto_ptr WriteGuardType;\n" - " virtual WriteGuardType getWriteGuard(bool enabledGuard = true);\n" - "};\n" - "class SafeSharedMemory : public Guarded\n" - "{\n" - "};"); - ASSERT_EQUALS("", errout.str()); - - check("void foo()\n" - "{\n" - " auto_ptr< ns1:::MyClass > y;\n" - "}"); - ASSERT_EQUALS("", errout.str()); - - check("void f()\n" - "{\n" - " auto_ptr p2;\n" - " p2 = new T;\n" - "}"); - ASSERT_EQUALS("", errout.str()); - - check("void foo()\n" - "{\n" - " std::vector< std::auto_ptr< ns1::MyClass> > v;\n" - "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) You can randomly lose access to pointers if you store 'auto_ptr' pointers in an STL container.\n", errout.str()); - - check("void foo()\n" - "{\n" - " std::vector< auto_ptr< MyClass> > v;\n" - "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) You can randomly lose access to pointers if you store 'auto_ptr' pointers in an STL container.\n", errout.str()); - - check("void foo()\n" - "{\n" - " int *i = new int;\n" - " auto_ptr x(i);\n" - " auto_ptr y;\n" - " y = x;\n" - "}"); - ASSERT_EQUALS("[test.cpp:6]: (style) Copying 'auto_ptr' pointer to another does not create two equal objects since one has lost its ownership of the pointer.\n", errout.str()); - - check("std::auto_ptr function();\n" - "int quit;" - "void f() { quit = true; }\n" - ); - ASSERT_EQUALS("", errout.str()); - - // ticket #748 - check("void f()\n" - "{\n" - " T* var = new T[10];\n" - " auto_ptr p2( var );\n" - "}"); - ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str()); - - check("void f()\n" - "{\n" - " foo::bar::baz* var = new foo::bar::baz[10];\n" - " auto_ptr p2( var );\n" - "}"); - ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str()); - - check("void f()\n" - "{\n" - " auto_ptr p2( new T[] );\n" - "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str()); - - check("void f()\n" - "{\n" - " auto_ptr p2( new T[5] );\n" - "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str()); - - check("void f()\n" - "{\n" - " auto_ptr p(new foo::bar[10]);\n" - "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str()); - - check("void f()\n" - "{\n" - " auto_ptr p2;\n" - " p2.reset( new T[] );\n" - "}"); - ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str()); - - - check("void f()\n" - "{\n" - " auto_ptr p2( new T[][] );\n" - "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str()); - - check("void f()\n" - "{\n" - " auto_ptr p2;\n" - " p2 = new T[10];\n" - "}"); - ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str()); - - check("void f()\n" - "{\n" - " auto_ptr p2;\n" - " p2 = new T::B[10];\n" - "}"); - ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str()); - - check("void f()\n" - "{\n" - " auto_ptr p2;\n" - " p2.reset( new T[10] );\n" - "}"); - ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str()); - - check("void f()\n" - "{\n" - " auto_ptr p2;\n" - " p2.reset( new T::B[10] );\n" - "}"); - ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with operator 'new[]'.\n", errout.str()); - - // ticket #2887 (infinite loop) - check("A::A(std::auto_ptr e){}"); - ASSERT_EQUALS("", errout.str()); - - // ticket #4390 - check("auto_ptr CreateRegistryStringStorage() {\n" - " return auto_ptr(new RegistryConnectionStringStorage());\n" - "}\n" - "\n" - "void LookupWindowsUserAccountName() {\n" - " auto_ptr_array domainName(new char[42]);\n" - "}"); - ASSERT_EQUALS("", errout.str()); - - // ticket #749 - check("int main()\n" - "{\n" - " int *i = malloc(sizeof(int));\n" - " auto_ptr x(i);\n" - "}"); - ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str()); - - check("int main()\n" - "{\n" - " auto_ptr x((int*)malloc(sizeof(int)*4));\n" - "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str()); - - check("int main()\n" - "{\n" - " auto_ptr b(static_cast(malloc(sizeof(int)*4)));\n" - "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str()); - - check("int main()\n" - "{\n" - " auto_ptr x = (int*)malloc(sizeof(int)*4);\n" - "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str()); - - check("int main()\n" - "{\n" - " auto_ptr x = static_cast(malloc(sizeof(int)*4));\n" - "}"); - ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str()); - - check("int main()\n" - "{\n" - " auto_ptr x;\n" - " x.reset((int*)malloc(sizeof(int)*4));\n" - "}"); - ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str()); - - check("int main()\n" - "{\n" - " auto_ptr x;\n" - " x.reset(static_cast(malloc(sizeof(int)*4)));\n" - "}"); - ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str()); - } - void uselessCalls() { check("void f()\n" "{\n"