diff --git a/src/checkmemoryleak.cpp b/src/checkmemoryleak.cpp index b6fc64a2c..529a783ae 100644 --- a/src/checkmemoryleak.cpp +++ b/src/checkmemoryleak.cpp @@ -1964,7 +1964,7 @@ void CheckMemoryLeakStructMember::check() // Check struct.. unsigned int indentlevel2 = 0; - for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) + for (const Token *tok2 = vartok; tok2; tok2 = tok2->next()) { if (tok2->str() == "{") ++indentlevel2; @@ -2001,7 +2001,29 @@ void CheckMemoryLeakStructMember::check() // Deallocating the struct member.. else if (Token::Match(tok3, "free|kfree ( %var% . %varid% )", structmemberid)) - break; + { + // If the deallocation happens at the base level, don't check this member anymore + if (indentlevel3 == 0) + break; + + // deallocating and then returning from function in a conditional block => + // skip ahead out of the block + bool ret = false; + while (tok3) + { + // debug info + const std::string tok3str_(tok3->str()); + if (tok3->str() == "return") + ret = true; + else if (tok3->str() == "{" || tok3->str() == "}") + break; + tok3 = tok3->next(); + } + if (!ret || !tok3 || tok3->str() != "}") + break; + --indentlevel3; + continue; + } // Deallocating the struct.. else if (Token::Match(tok3, "free|kfree ( %varid% )", structid)) diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 8a81fe521..8ea718835 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -2873,6 +2873,18 @@ private: " return abc;\n" "}\n"); ASSERT_EQUALS("[test.cpp:8]: (error) Memory leak: abc.a\n", errout.str()); + + check("static void foo(int a)\n" + "{\n" + " ABC *abc = malloc(sizeof(ABC));\n" + " abc->a = malloc(10);\n" + " if (a == 1)\n" + " {\n" + " free(abc->a);\n" + " return;\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:10]: (error) Memory leak: abc.a\n", errout.str()); } void goto_()