Fixed #1649 (add a warning for potential memory leaks when using realloc)

This commit is contained in:
Zachary Blair 2010-05-17 22:46:48 -07:00
parent 0d7474042a
commit 1539c0b3d2
4 changed files with 53 additions and 6 deletions

View File

@ -337,6 +337,11 @@ void CheckMemoryLeak::memleakError(const Token *tok, const std::string &varname)
reportErr(tok, Severity::error, "memleak", "Memory leak: " + varname);
}
void CheckMemoryLeak::memleakUponReallocFailureError(const Token *tok, const std::string &varname)
{
reportErr(tok, Severity::error, "memleakOnRealloc", "Memory leak: \"" + varname + "\" nulled but not freed upon failure");
}
void CheckMemoryLeak::resourceLeakError(const Token *tok, const std::string &varname)
{
std::string errmsg("Resource leak");
@ -2103,6 +2108,29 @@ void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const std::string
//---------------------------------------------------------------------------
// Check for memory leaks due to improper realloc() usage.
// Below, "a" may be set to null without being freed if realloc() cannot
// allocate the requested memory:
// a = malloc(10); a = realloc(a, 100);
//---------------------------------------------------------------------------
void CheckMemoryLeakInFunction::checkReallocUsage()
{
const Token *tok = _tokenizer->tokens();
for (; tok; tok = tok->next())
{
if (Token::Match(tok, "%var% = realloc|g_try_realloc ( %var% ,"))
{
if (tok->varId() == tok->tokAt(4)->varId())
{
memleakUponReallocFailureError(tok, tok->str());
}
}
}
}
//---------------------------------------------------------------------------

View File

@ -140,6 +140,7 @@ public:
void deallocuseError(const Token *tok, const std::string &varname);
void mismatchSizeError(const Token *tok, const std::string &sz);
void mismatchAllocDealloc(const std::list<const Token *> &callstack, const std::string &varname);
void memleakUponReallocFailureError(const Token *tok, const std::string &varname);
/** What type of allocated memory does the given function return? */
AllocType functionReturnType(const Token *tok) const;
@ -179,6 +180,7 @@ public:
void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
{
CheckMemoryLeakInFunction checkMemoryLeak(tokenizr, settings, errLog);
checkMemoryLeak.checkReallocUsage();
checkMemoryLeak.check();
}
@ -191,6 +193,11 @@ public:
/** @brief experimental: checking via ExecutionPath */
void localleaks();
/**
* Checking for a memory leak caused by improper realloc usage.
*/
void checkReallocUsage();
/**
* @brief %Check all variables in function scope
* @param tok The first '{' token of the function body
@ -298,6 +305,7 @@ public:
mismatchSizeError(0, "sz");
std::list<const Token *> callstack;
mismatchAllocDealloc(callstack, "varname");
memleakUponReallocFailureError(0, "varname");
}
/**

View File

@ -5187,6 +5187,15 @@ bool Tokenizer::simplifyKnownVariables()
break;
}
// Variable used in realloc (see Ticket #1649)
if (Token::Match(tok3, "%var% = realloc ( %var% ,") &&
tok3->varId() == varid &&
tok3->tokAt(4)->varId() == varid)
{
tok3->tokAt(4)->str(value);
ret = true;
}
// Variable is used somehow in a non-defined pattern => bail out
if (tok3->varId() == varid)
break;

View File

@ -216,7 +216,7 @@ private:
settings.inconclusive = showAll;
tokenizer.fillFunctionList();
CheckMemoryLeakInFunction checkMemoryLeak(&tokenizer, &settings, this);
checkMemoryLeak.check();
checkMemoryLeak.runSimplifiedChecks(&tokenizer, &settings, this);
}
@ -1085,7 +1085,7 @@ private:
" ;\n"
" free(buf);\n"
"}\n");
TODO_ASSERT_EQUALS("[test.cpp:6]: (error) Memory leak: buf\n", errout.str());
ASSERT_EQUALS("[test.cpp:6]: (error) Memory leak: \"buf\" nulled but not freed upon failure\n", errout.str());
}
void if11()
@ -1174,7 +1174,7 @@ private:
"\n"
" return a;\n"
"}\n", true);
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[test.cpp:9]: (error) Memory leak: \"a\" nulled but not freed upon failure\n", errout.str());
}
@ -1195,7 +1195,8 @@ private:
"\n"
" return a;\n"
"}\n", true);
ASSERT_EQUALS("[test.cpp:11]: (error) Memory leak: a\n", errout.str());
ASSERT_EQUALS("[test.cpp:9]: (error) Memory leak: \"a\" nulled but not freed upon failure\n"
"[test.cpp:11]: (error) Memory leak: a\n", errout.str());
}
@ -1791,7 +1792,8 @@ private:
" char *a = (char *)malloc(10);\n"
" a = realloc(a, 100);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: a\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: \"a\" nulled but not freed upon failure\n"
"[test.cpp:5]: (error) Memory leak: a\n", errout.str());
}
void realloc2()
@ -1803,7 +1805,7 @@ private:
" free(a);\n"
"}\n");
TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: a\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: \"a\" nulled but not freed upon failure\n", errout.str());
}
void realloc3()