From 38213f1f2fa68318e1506294c236761823b9c6ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 27 Oct 2012 16:36:14 +0200 Subject: [PATCH] Fixed #4237 (False positive: (error) Memory Leak: data (assign reference variable value to a shadow variable in inner scope)) --- lib/checkleakautovar.cpp | 6 ++++++ lib/checkleakautovar.h | 3 +++ lib/checkmemoryleak.cpp | 5 +++++ test/testleakautovar.cpp | 11 +++++++++++ test/testmemleak.cpp | 3 +++ 5 files changed, 28 insertions(+) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 6741aab43..da9f6bac1 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -250,6 +250,8 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken, } else if (Token::simpleMatch(tok->previous(), "=")) { varInfo->erase(tok->varId()); } + } else if (Token::Match(tok->previous(), "& %var% = %var% ;")) { + varInfo->referenced.insert(tok->tokAt(2)->varId()); } } @@ -557,6 +559,10 @@ void CheckLeakAutoVar::ret(const Token *tok, const VarInfo &varInfo) if (it->second != "dealloc" && varInfo.conditionalAlloc.find(it->first) != varInfo.conditionalAlloc.end()) continue; + // don't warn if there is a reference of the variable + if (varInfo.referenced.find(it->first) != varInfo.referenced.end()) + continue; + const unsigned int varid = it->first; const Variable *var = symbolDatabase->getVariableFromVarId(varid); if (var) { diff --git a/lib/checkleakautovar.h b/lib/checkleakautovar.h index a6d3e76fe..a0ecd7b65 100644 --- a/lib/checkleakautovar.h +++ b/lib/checkleakautovar.h @@ -31,11 +31,13 @@ public: std::map alloctype; std::map possibleUsage; std::set conditionalAlloc; + std::set referenced; void clear() { alloctype.clear(); possibleUsage.clear(); conditionalAlloc.clear(); + referenced.clear(); } void erase(unsigned int varid) { @@ -48,6 +50,7 @@ public: alloctype.swap(other.alloctype); possibleUsage.swap(other.possibleUsage); conditionalAlloc.swap(other.conditionalAlloc); + referenced.swap(other.referenced); } /** set possible usage for all variables */ diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 39f5dbba8..8c85af768 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -1246,6 +1246,11 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::listnext()) + rethead->deleteNext(); + return rethead; + } if (Token::Match(tok, "[)=] %varid% [+;)]", varid) || Token::Match(tok, "%var% + %varid%", varid) || Token::Match(tok, "%varid% +=|-=", varid) || diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 04cca6ee4..a5881563a 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -45,6 +45,7 @@ private: TEST_CASE(assign10); TEST_CASE(assign11); // #3942: x = a(b(p)); TEST_CASE(assign12); // #4236: FP. bar(&x); + TEST_CASE(assign13); // #4237: FP. char*&ref=p; p=malloc(10); free(ref); TEST_CASE(deallocuse1); TEST_CASE(deallocuse2); @@ -228,6 +229,16 @@ private: ASSERT_EQUALS("", errout.str()); } + void assign13() { // #4237: FP. char *&ref=p; p=malloc(10); free(ref); + check("void f() {\n" + " char *p;\n" + " char * &ref = p;\n" + " p = malloc(10);\n" + " free(ref);\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 c3e149a9a..48a59d691 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -506,6 +506,9 @@ private: // non-use.. ASSERT_EQUALS(";;", getcode("char *s; s = s + 1;", "s")); + // reference + ASSERT_EQUALS(";", getcode("char *p; char * & ref = p; p = malloc(10);", "p")); + // return.. ASSERT_EQUALS(";;return;", getcode("char *s; return;", "s")); ASSERT_EQUALS(";;returnuse;", getcode("char *s; return s;", "s"));