diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index da847a439..6420b2188 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -22,6 +22,7 @@ #include "checkleakautovar.h" #include "checkmemoryleak.h" // <- CheckMemoryLeak::memoryLeak +#include "checknullpointer.h" // <- CheckNullPointer::isPointerDeRef #include "tokenize.h" #include "symboldatabase.h" #include "astutils.h" @@ -196,7 +197,8 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken, if (tok->varId() > 0) { const std::map::const_iterator var = alloctype.find(tok->varId()); if (var != alloctype.end()) { - if (var->second.status == VarInfo::DEALLOC && tok->strAt(-1) != "&" && (!Token::Match(tok, "%name% =") || tok->strAt(-1) == "*")) { + bool unknown = false; + if (var->second.status == VarInfo::DEALLOC && CheckNullPointer::isPointerDeRef(tok,unknown) && !unknown) { deallocUseError(tok, tok->str()); } else if (Token::simpleMatch(tok->tokAt(-2), "= &")) { varInfo->erase(tok->varId()); diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 7f6b7590d..d821bac87 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -162,6 +162,8 @@ bool CheckNullPointer::isPointerDeRef(const Token *tok, bool &unknown) const Token* parent = tok->astParent(); if (!parent) return false; + if (parent->str() == "." && parent->astOperand2() == tok) + return isPointerDeRef(parent, unknown); const bool firstOperand = parent->astOperand1() == tok; while (parent->str() == "(" && (parent->astOperand2() == nullptr && parent->strAt(1) != ")")) { // Skip over casts parent = parent->astParent(); diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index bcc7a20a3..dc143a286 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -65,6 +65,7 @@ private: TEST_CASE(doublefree2); TEST_CASE(doublefree3); // #4914 TEST_CASE(doublefree4); // #5451 - FP when exit is called + TEST_CASE(doublefree5); // #5522 // exit TEST_CASE(exit1); @@ -812,6 +813,15 @@ private: ASSERT_EQUALS("", errout.str()); } + void doublefree5() { // #5522 + check("void f(char *p) {\n" + " free(p);\n" + " x = (q == p);\n" + " free(p);\n" + "}"); + ASSERT_EQUALS("[test.c:4]: (error) Memory pointed to by 'p' is freed twice.\n", errout.str()); + } + void exit1() { check("void f() {\n" " char *p = malloc(10);\n"