Fixed #4867 (Memory Leak: Return value of malloc)
This commit is contained in:
parent
b411efa33f
commit
7a6386bc4b
|
@ -2702,6 +2702,9 @@ void CheckMemoryLeakNoVar::check()
|
|||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
|
||||
// Checks if a call to an allocation function like malloc() is made and its return value is not assigned.
|
||||
checkForUnusedReturnValue(scope);
|
||||
|
||||
// goto the "}" that ends the executable scope..
|
||||
const Token *tok = scope->classEnd;
|
||||
|
||||
|
@ -2743,7 +2746,27 @@ void CheckMemoryLeakNoVar::check()
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Checks if a call to an allocation function like malloc() is made and its return value is not assigned.
|
||||
//---------------------------------------------------------------------------
|
||||
void CheckMemoryLeakNoVar::checkForUnusedReturnValue(const Scope *scope)
|
||||
{
|
||||
for (const Token *tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
|
||||
if (Token::Match(tok, "{|}|; %var% (")) {
|
||||
tok = tok->next();
|
||||
const int allocationId = _settings->library.alloc(tok->str());
|
||||
if (allocationId > 0)
|
||||
returnValueNotUsedError(tok, tok->str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckMemoryLeakNoVar::functionCallLeak(const Token *loc, const std::string &alloc, const std::string &functionCall)
|
||||
{
|
||||
reportError(loc, Severity::error, "leakNoVarFunctionCall", "Allocation with " + alloc + ", " + functionCall + " doesn't release it.");
|
||||
}
|
||||
|
||||
void CheckMemoryLeakNoVar::returnValueNotUsedError(const Token *tok, const std::string &alloc)
|
||||
{
|
||||
reportError(tok, Severity::error, "leakReturnValNotUsed", "Return value of allocation function " + alloc + " is not used.");
|
||||
}
|
||||
|
|
|
@ -449,13 +449,20 @@ public:
|
|||
void check();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief %Check if a call to an allocation function like malloc() is made and its return value is not assigned.
|
||||
* @param scope The scope of the function to check.
|
||||
*/
|
||||
void checkForUnusedReturnValue(const Scope *scope);
|
||||
|
||||
void functionCallLeak(const Token *loc, const std::string &alloc, const std::string &functionCall);
|
||||
void returnValueNotUsedError(const Token* tok, const std::string &alloc);
|
||||
|
||||
void getErrorMessages(ErrorLogger *e, const Settings *settings) const {
|
||||
CheckMemoryLeakNoVar c(0, settings, e);
|
||||
|
||||
c.functionCallLeak(0, "funcName", "funcName");
|
||||
c.returnValueNotUsedError(0, "funcName");
|
||||
}
|
||||
|
||||
static std::string myName() {
|
||||
|
|
|
@ -1053,15 +1053,6 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: str\n", errout.str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ifelse6() {
|
||||
check("static char *f()\n"
|
||||
"{\n"
|
||||
|
@ -5495,6 +5486,16 @@ private:
|
|||
Settings settings;
|
||||
settings.standards.posix = true;
|
||||
|
||||
// Add some test allocation functions to the library.
|
||||
// When not run as a unit test, these are read from
|
||||
// an XML file (e.g. cfg/posix.cfg).
|
||||
int id = 0;
|
||||
while (!settings.library.ismemory(++id))
|
||||
continue;
|
||||
settings.library.setalloc("malloc", id);
|
||||
settings.library.setalloc("calloc", id);
|
||||
settings.library.setalloc("strdup", id);
|
||||
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer(&settings, this);
|
||||
std::istringstream istr(code);
|
||||
|
@ -5510,7 +5511,7 @@ private:
|
|||
// pass allocated memory to function..
|
||||
TEST_CASE(functionParameter);
|
||||
// never use leakable resource
|
||||
TEST_CASE(missingAssignement);
|
||||
TEST_CASE(missingAssignment);
|
||||
}
|
||||
|
||||
void functionParameter() {
|
||||
|
@ -5549,11 +5550,43 @@ private:
|
|||
TODO_ASSERT_EQUALS("[test.cpp:4]: (error) Allocation with strdup, mkstemp doesn't release it.\n", "", errout.str());
|
||||
}
|
||||
|
||||
void missingAssignement() {
|
||||
void missingAssignment() {
|
||||
check("void x()\n"
|
||||
"{\n"
|
||||
" malloc(10);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Return value of allocation function malloc is not used.\n", errout.str());
|
||||
|
||||
check("void x()\n"
|
||||
"{\n"
|
||||
" calloc(10);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Return value of allocation function calloc is not used.\n", errout.str());
|
||||
|
||||
check("void x()\n"
|
||||
"{\n"
|
||||
" strdup(\"Test\");\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Return value of allocation function strdup is not used.\n", errout.str());
|
||||
|
||||
check("void x()\n"
|
||||
"{\n"
|
||||
" (char*) malloc(10);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Return value of allocation function malloc is not used.\n", errout.str());
|
||||
|
||||
check("void x()\n"
|
||||
"{\n"
|
||||
" char* ptr = malloc(10);\n"
|
||||
" foo(ptr);\n"
|
||||
" free(ptr);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("void x()\n"
|
||||
"{\n"
|
||||
" 42,malloc(42);\n"
|
||||
"}");
|
||||
TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Return value of allocation function malloc is not used.\n", "", errout.str());
|
||||
|
||||
check("void *f()\n"
|
||||
|
|
Loading…
Reference in New Issue