Fixed #4867 (Memory Leak: Return value of malloc)

This commit is contained in:
Zachary Blair 2014-01-03 10:12:32 +01:00 committed by Daniel Marjamäki
parent b411efa33f
commit 7a6386bc4b
3 changed files with 74 additions and 11 deletions

View File

@ -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.");
}

View File

@ -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() {

View File

@ -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"