diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index afee74b4f..dbc52ee78 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -78,6 +78,11 @@ void CheckLeakAutoVar::deallocUseError(const Token *tok, const std::string &varn reportError(tok, Severity::error, "newdeallocuse", "Using deallocated pointer " + varname); } +void CheckLeakAutoVar::deallocReturnError(const Token *tok, const std::string &varname) +{ + reportError(tok, Severity::error, "newdeallocret", "Returning/using deallocated pointer " + varname); +} + void CheckLeakAutoVar::doubleDeallocationError(const Token *tok, const std::string &varname) { reportError(tok, Severity::error, "doubledeallocation", "Double deallocation: " + varname); @@ -461,12 +466,8 @@ void CheckLeakAutoVar::ret(const Token *tok, const VarInfo &varInfo) const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); for (std::map::const_iterator it = alloctype.begin(); it != alloctype.end(); ++it) { - // has pointer been deallocated? - if (it->second == "dealloc") - continue; - // don't warn if variable is conditionally allocated - if (varInfo.conditionalAlloc.find(it->first) != varInfo.conditionalAlloc.end()) + if (it->second != "dealloc" && varInfo.conditionalAlloc.find(it->first) != varInfo.conditionalAlloc.end()) continue; const unsigned int varid = it->first; @@ -485,14 +486,19 @@ void CheckLeakAutoVar::ret(const Token *tok, const VarInfo &varInfo) break; } } - if (used) - continue; - const std::map::const_iterator use = possibleUsage.find(varid); - if (use == possibleUsage.end()) { - leakError(tok, var->name()); - } else { - configurationInfo(tok, use->second); + // return deallocated pointer + if (used && it->second == "dealloc") + deallocReturnError(tok, var->name()); + + else if (!used && it->second != "dealloc") { + + const std::map::const_iterator use = possibleUsage.find(varid); + if (use == possibleUsage.end()) { + leakError(tok, var->name()); + } else { + configurationInfo(tok, use->second); + } } } } diff --git a/lib/checkleakautovar.h b/lib/checkleakautovar.h index 303e658aa..424c13d81 100644 --- a/lib/checkleakautovar.h +++ b/lib/checkleakautovar.h @@ -109,6 +109,7 @@ private: void leakError(const Token* tok, const std::string &varname); void mismatchError(const Token* tok, const std::string &varname); void deallocUseError(const Token *tok, const std::string &varname); + void deallocReturnError(const Token *tok, const std::string &varname); void doubleDeallocationError(const Token *tok, const std::string &varname); /** message: user configuration is needed to complete analysis */ diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index ce030ff75..538f4f7f2 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -47,6 +47,7 @@ private: TEST_CASE(deallocuse1); TEST_CASE(deallocuse2); TEST_CASE(deallocuse3); + TEST_CASE(deallocuse4); TEST_CASE(doublefree); @@ -232,6 +233,14 @@ private: ASSERT_EQUALS("[test.c:3]: (error) Using deallocated pointer p\n", errout.str()); } + void deallocuse4() { + check("void f(char *p) {\n" + " free(p);\n" + " return p;\n" + "}"); + ASSERT_EQUALS("[test.c:3]: (error) Returning/using deallocated pointer p\n", errout.str()); + } + void doublefree() { check("void f(char *p) {\n" " free(p);\n"