Fixed #1649 (add a warning for potential memory leaks when using realloc)
This commit is contained in:
parent
0d7474042a
commit
1539c0b3d2
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue