diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index e7c288359..6741aab43 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -506,6 +506,8 @@ void CheckLeakAutoVar::functionCall(const Token *tok, VarInfo *varInfo, const st if (dealloc.empty()) { // possible usage possibleUsage[arg->varId()] = tok->str(); + if (var->second == "dealloc" && arg->previous()->str() == "&") + varInfo->erase(arg->varId()); } else if (var->second == "dealloc") { CheckOther checkOther(_tokenizer, _settings, _errorLogger); checkOther.doubleFreeError(tok, arg->str()); diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index a1b09f814..39f5dbba8 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -2013,6 +2013,8 @@ void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const std::string Token *tok = getcode(Tok1, callstack, varid, alloctype, dealloctype, classmember, sz); //tok->printOut((std::string("Checkmemoryleak: getcode result for: ") + varname).c_str()); + const bool use_addr = bool(Token::findsimplematch(tok, "&use") != NULL); + // Simplify the code and check if freed memory is used.. for (Token *tok2 = tok; tok2; tok2 = tok2->next()) { while (Token::Match(tok2, "[;{}] ;")) @@ -2071,7 +2073,7 @@ void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const std::string memoryLeak(result, varname, alloctype); } - else if ((result = Token::findsimplematch(tok, "dealloc ; dealloc ;")) != NULL) { + else if (!use_addr && (result = Token::findsimplematch(tok, "dealloc ; dealloc ;")) != NULL) { deallocDeallocError(result->tokAt(2), varname); } diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index ae06ab199..04cca6ee4 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -44,6 +44,7 @@ private: TEST_CASE(assign9); TEST_CASE(assign10); TEST_CASE(assign11); // #3942: x = a(b(p)); + TEST_CASE(assign12); // #4236: FP. bar(&x); TEST_CASE(deallocuse1); TEST_CASE(deallocuse2); @@ -217,6 +218,16 @@ private: ASSERT_EQUALS("[test.c:4]: (information) b configuration is needed to establish if there is a leak or not\n", errout.str()); } + void assign12() { // #4236: FP. bar(&x) + check("void f() {\n" + " char *p = malloc(10);\n" + " free(p);\n" + " bar(&p);\n" + " free(p);\n" + "}"); + ASSERT_EQUALS("", errout.str()); + } + void deallocuse1() { check("void f(char *p) {\n" " free(p);\n" diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index c2b54c8e0..c3e149a9a 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -281,6 +281,7 @@ private: // free a free'd pointer TEST_CASE(freefree1); TEST_CASE(freefree2); + TEST_CASE(freefree3); // #4236 - FP. bar(&p) TEST_CASE(strcpy_result_assignment); TEST_CASE(strcat_result_assignment); @@ -3020,6 +3021,17 @@ private: ASSERT_EQUALS("", errout.str()); } + void freefree3() { + check("void foo()\n" + "{\n" + " char *p = malloc(10);\n" + " free(p);\n" + " bar(&p);\n" + " free(p);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } + void strcpy_result_assignment() { check("void foo()\n" "{\n"