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);
|
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)
|
void CheckMemoryLeak::resourceLeakError(const Token *tok, const std::string &varname)
|
||||||
{
|
{
|
||||||
std::string errmsg("Resource leak");
|
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 deallocuseError(const Token *tok, const std::string &varname);
|
||||||
void mismatchSizeError(const Token *tok, const std::string &sz);
|
void mismatchSizeError(const Token *tok, const std::string &sz);
|
||||||
void mismatchAllocDealloc(const std::list<const Token *> &callstack, const std::string &varname);
|
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? */
|
/** What type of allocated memory does the given function return? */
|
||||||
AllocType functionReturnType(const Token *tok) const;
|
AllocType functionReturnType(const Token *tok) const;
|
||||||
|
@ -179,6 +180,7 @@ public:
|
||||||
void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
|
void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
|
||||||
{
|
{
|
||||||
CheckMemoryLeakInFunction checkMemoryLeak(tokenizr, settings, errLog);
|
CheckMemoryLeakInFunction checkMemoryLeak(tokenizr, settings, errLog);
|
||||||
|
checkMemoryLeak.checkReallocUsage();
|
||||||
checkMemoryLeak.check();
|
checkMemoryLeak.check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,6 +193,11 @@ public:
|
||||||
/** @brief experimental: checking via ExecutionPath */
|
/** @brief experimental: checking via ExecutionPath */
|
||||||
void localleaks();
|
void localleaks();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checking for a memory leak caused by improper realloc usage.
|
||||||
|
*/
|
||||||
|
void checkReallocUsage();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief %Check all variables in function scope
|
* @brief %Check all variables in function scope
|
||||||
* @param tok The first '{' token of the function body
|
* @param tok The first '{' token of the function body
|
||||||
|
@ -298,6 +305,7 @@ public:
|
||||||
mismatchSizeError(0, "sz");
|
mismatchSizeError(0, "sz");
|
||||||
std::list<const Token *> callstack;
|
std::list<const Token *> callstack;
|
||||||
mismatchAllocDealloc(callstack, "varname");
|
mismatchAllocDealloc(callstack, "varname");
|
||||||
|
memleakUponReallocFailureError(0, "varname");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5187,6 +5187,15 @@ bool Tokenizer::simplifyKnownVariables()
|
||||||
break;
|
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
|
// Variable is used somehow in a non-defined pattern => bail out
|
||||||
if (tok3->varId() == varid)
|
if (tok3->varId() == varid)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -216,7 +216,7 @@ private:
|
||||||
settings.inconclusive = showAll;
|
settings.inconclusive = showAll;
|
||||||
tokenizer.fillFunctionList();
|
tokenizer.fillFunctionList();
|
||||||
CheckMemoryLeakInFunction checkMemoryLeak(&tokenizer, &settings, this);
|
CheckMemoryLeakInFunction checkMemoryLeak(&tokenizer, &settings, this);
|
||||||
checkMemoryLeak.check();
|
checkMemoryLeak.runSimplifiedChecks(&tokenizer, &settings, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1085,7 +1085,7 @@ private:
|
||||||
" ;\n"
|
" ;\n"
|
||||||
" free(buf);\n"
|
" free(buf);\n"
|
||||||
"}\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()
|
void if11()
|
||||||
|
@ -1174,7 +1174,7 @@ private:
|
||||||
"\n"
|
"\n"
|
||||||
" return a;\n"
|
" return a;\n"
|
||||||
"}\n", true);
|
"}\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"
|
"\n"
|
||||||
" return a;\n"
|
" return a;\n"
|
||||||
"}\n", true);
|
"}\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"
|
" char *a = (char *)malloc(10);\n"
|
||||||
" a = realloc(a, 100);\n"
|
" a = realloc(a, 100);\n"
|
||||||
"}\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()
|
void realloc2()
|
||||||
|
@ -1803,7 +1805,7 @@ private:
|
||||||
" free(a);\n"
|
" free(a);\n"
|
||||||
"}\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()
|
void realloc3()
|
||||||
|
|
Loading…
Reference in New Issue