diff --git a/lib/checkautovariables.cpp b/lib/checkautovariables.cpp index fab5770fa..6e31495cf 100644 --- a/lib/checkautovariables.cpp +++ b/lib/checkautovariables.cpp @@ -266,16 +266,16 @@ void CheckAutoVariables::autoVariables() errorAutoVariableAssignment(tok->next(), false); } // Invalid pointer deallocation - else if ((Token::Match(tok, "%name% ( %var% ) ;") && mSettings->library.getDeallocFuncInfo(tok)) || - (mTokenizer->isCPP() && Token::Match(tok, "delete [| ]| (| %var% !!["))) { - tok = Token::findmatch(tok->next(), "%var%"); - if (isArrayVar(tok)) + else if ((Token::Match(tok, "%name% ( %var%|%str% ) ;") && mSettings->library.getDeallocFuncInfo(tok)) || + (mTokenizer->isCPP() && Token::Match(tok, "delete [| ]| (| %var%|%str% !!["))) { + tok = Token::findmatch(tok->next(), "%var%|%str%"); + if (isArrayVar(tok) || tok->tokType() == Token::eString) errorInvalidDeallocation(tok, nullptr); else if (tok->variable() && tok->variable()->isPointer()) { for (const ValueFlow::Value &v : tok->values()) { if (!(v.isTokValue())) continue; - if (isArrayVar(v.tokvalue)) { + if (isArrayVar(v.tokvalue) || v.tokvalue->tokType() == Token::eString) { errorInvalidDeallocation(tok, &v); break; } @@ -804,7 +804,11 @@ void CheckAutoVariables::errorInvalidDeallocation(const Token *tok, const ValueF const Variable *var = val ? val->tokvalue->variable() : (tok ? tok->variable() : nullptr); std::string type = "auto-variable"; - if (var) { + if (tok && tok->tokType() == Token::eString) + type = "string literal"; + else if (val && val->tokvalue->tokType() == Token::eString) + type = "pointer pointing to a string literal"; + else if (var) { if (var->isGlobal()) type = "global variable"; else if (var->isStatic()) diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index d92f175b6..2c627139a 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -79,6 +79,7 @@ private: TEST_CASE(testautovar_extern); TEST_CASE(testautovar_reassigned); TEST_CASE(testinvaliddealloc); + TEST_CASE(testinvaliddealloc_string); TEST_CASE(testinvaliddealloc_C); TEST_CASE(testassign1); // Ticket #1819 TEST_CASE(testassign2); // Ticket #2765 @@ -627,6 +628,11 @@ private: "[test.cpp:9]: (error) Deallocation of an auto-variable results in undefined behaviour.\n" "[test.cpp:11]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", errout.str()); + check("void func1(char * ptr) {\n" + " free(ptr);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + check("void func1() {\n" " char* tmp1[256];\n" " init(tmp1);\n" @@ -758,6 +764,26 @@ private: ASSERT_EQUALS("", errout.str()); } + void testinvaliddealloc_string() { + // #7341 + check("void f() {\n" + " char *ptr = \"a\";\n" + " free(\"a\");\n" + " delete \"a\";\n" + " free(ptr);\n" + " delete ptr;\n" + " char * p = malloc(1000);\n" + " p = \"abc\";\n" + " free(p);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an string literal results in undefined behaviour.\n" + "[test.cpp:4]: (error) Deallocation of an string literal results in undefined behaviour.\n" + "[test.cpp:5]: (error) Deallocation of an pointer pointing to a string literal (\"a\") results in undefined behaviour.\n" + "[test.cpp:6]: (error) Deallocation of an pointer pointing to a string literal (\"a\") results in undefined behaviour.\n" + "[test.cpp:9]: (error) Deallocation of an pointer pointing to a string literal (\"abc\") results in undefined behaviour.\n", + errout.str()); + } + void testinvaliddealloc_C() { // #5691 check("void svn_repos_dir_delta2() {\n"