diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index e13cda5bd..7a97acaac 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -362,8 +362,20 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken, VarInfo old; old.swap(*varInfo); - // Conditional allocation in varInfo1 std::map::const_iterator it; + + for (it = old.alloctype.begin(); it != old.alloctype.end(); ++it) { + const unsigned int varId = it->first; + if (old.conditionalAlloc.find(varId) == old.conditionalAlloc.end()) + continue; + if (varInfo1.alloctype.find(varId) == varInfo1.alloctype.end() || + varInfo2.alloctype.find(varId) == varInfo2.alloctype.end()) { + varInfo1.erase(varId); + varInfo2.erase(varId); + } + } + + // Conditional allocation in varInfo1 for (it = varInfo1.alloctype.begin(); it != varInfo1.alloctype.end(); ++it) { if (varInfo2.alloctype.find(it->first) == varInfo2.alloctype.end() && old.alloctype.find(it->first) == old.alloctype.end()) { diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 311d50c19..3b685698c 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -98,6 +98,7 @@ private: TEST_CASE(return2); TEST_CASE(return3); TEST_CASE(return4); + TEST_CASE(return5); // General tests: variable type, allocation type, etc TEST_CASE(test1); @@ -1043,6 +1044,20 @@ private: ASSERT_EQUALS("", errout.str()); } + void return5() { // ticket #6397 - conditional allocation/deallocation and conditional return + // avoid false positives + check("void f(int *p, int x) {\n" + " if (x != 0) {\n" + " free(p);\n" + " }\n" + " if (x != 0) {\n" + " return;\n" + " }\n" + " *p = 0;\n" + "}", true); + ASSERT_EQUALS("", errout.str()); + } + void test1() { // 3809 check("void f(double*&p) {\n" " p = malloc(0x100);\n"