diff --git a/src/checkmemoryleak.cpp b/src/checkmemoryleak.cpp index d525ca81d..288c1172a 100644 --- a/src/checkmemoryleak.cpp +++ b/src/checkmemoryleak.cpp @@ -53,7 +53,7 @@ bool CheckMemoryLeak::isclass(const Tokenizer *_tokenizer, const Token *tok) con } //--------------------------------------------------------------------------- -CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2) const +CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2, const char varname[]) const { // What we may have... // * var = (char *)malloc(10); @@ -87,6 +87,10 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2) return Malloc; } + // Using realloc.. + if (Token::Match(tok2, (std::string("realloc ( !!") + varname).c_str())) + return Malloc; + // Does tok2 point on "g_malloc", "g_strdup", .. static const char * const gmallocfunc[] = {"g_new", "g_new0", @@ -133,7 +137,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2) -CheckMemoryLeak::AllocType CheckMemoryLeak::getReallocationType(const Token *tok2) +CheckMemoryLeak::AllocType CheckMemoryLeak::getReallocationType(const Token *tok2, const char varname[]) { // What we may have... // * var = (char *)realloc(..; @@ -146,7 +150,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getReallocationType(const Token *tok if (! tok2) return No; - if (tok2->str() == "realloc") + if (Token::Match(tok2, (std::string("realloc ( ") + varname).c_str())) return Malloc; // GTK memory reallocation.. @@ -339,7 +343,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok) if (varname.empty() && Token::Match(tok, "%var% = ")) { varname = tok->str(); - allocType = getAllocationType(tok->tokAt(2)); + allocType = getAllocationType(tok->tokAt(2), varname.c_str()); if (allocType == No) return No; while (tok && tok->str() != ";") @@ -424,6 +428,10 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::liststr() == "delete") return 0; - if (getAllocationType(tok) != No || getReallocationType(tok) != No || getDeallocationType(tok, varnames) != No) + if (getAllocationType(tok, varnames[0]) != No || getReallocationType(tok, varnames[0]) != No || getDeallocationType(tok, varnames) != No) return 0; if (callstack.size() > 2) @@ -614,7 +622,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::listprevious(), std::string("[(;{}] " + varnameStr + " =").c_str())) { - AllocType alloc = getAllocationType(tok->tokAt(2)); + AllocType alloc = getAllocationType(tok->tokAt(2), varname); bool realloc = false; if (sz > 1 && @@ -626,7 +634,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::listtokAt(2)); + alloc = getReallocationType(tok->tokAt(2), varname); if (alloc != No) { addtoken("realloc"); @@ -947,7 +955,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::listtokAt(2), varnameStr.c_str()) ) { @@ -1879,7 +1887,7 @@ void CheckMemoryLeakInClass::variable(const char classname[], const Token *tokVa // Allocate.. if (indent == 0 || Token::Match(tok, (std::string(varname) + " =").c_str())) { - AllocType alloc = getAllocationType(tok->tokAt((indent > 0) ? 2 : 3)); + AllocType alloc = getAllocationType(tok->tokAt((indent > 0) ? 2 : 3), varname); if (alloc != CheckMemoryLeak::No) { if (Alloc != No && Alloc != alloc) diff --git a/src/checkmemoryleak.h b/src/checkmemoryleak.h index dddfec5da..9daef207a 100644 --- a/src/checkmemoryleak.h +++ b/src/checkmemoryleak.h @@ -94,12 +94,12 @@ public: /** * Get type of allocation at given position */ - AllocType getAllocationType(const Token *tok2) const; + AllocType getAllocationType(const Token *tok2, const char varname[]) const; /** * Get type of reallocation at given position */ - AllocType getReallocationType(const Token *tok2); + AllocType getReallocationType(const Token *tok2, const char varname[]); bool isclass(const Tokenizer *_tokenizer, const Token *typestr) const; diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index c2b195fc8..ba9078e59 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -19,7 +19,9 @@ #include "../src/tokenize.h" +#define private public #include "../src/checkmemoryleak.h" +#undef private #include "testsuite.h" #include @@ -223,6 +225,7 @@ private: TEST_CASE(realloc3); TEST_CASE(realloc4); TEST_CASE(realloc5); + TEST_CASE(realloc6); TEST_CASE(assign); @@ -1695,6 +1698,36 @@ private: ASSERT_EQUALS("", errout.str()); } + std::string getcode(const char code[], const char varname[]) const + { + // Tokenize.. + Tokenizer tokenizer; + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + // getcode.. + CheckMemoryLeakInFunction checkMemoryLeak; + std::list callstack; + CheckMemoryLeak::AllocType allocType, deallocType; + bool all = false; + Token *tokens = checkMemoryLeak.getcode(tokenizer.tokens(), callstack, varname, allocType, deallocType, false, all, 1); + + // stringify.. + std::string ret; + for (const Token *tok = tokens; tok; tok = tok->next()) + ret += tok->str(); + + Tokenizer::deleteTokens(tokens); + + return ret; + } + + void realloc6() + { + ASSERT_EQUALS(";;realloc;;", getcode(";buf=realloc(buf,100);", "buf")); + ASSERT_EQUALS(";;alloc;", getcode(";buf=realloc(0,100);", "buf")); + } + void assign() { check("void foo()\n"