Fixed #1648 (mismatch allocate and deallocate calls.)

This commit is contained in:
Daniel Marjamäki 2010-05-09 13:46:13 +02:00
parent 7c52c8683d
commit d7118c4d36
2 changed files with 79 additions and 32 deletions

View File

@ -397,47 +397,57 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok)
while (tok->str() != "{") while (tok->str() != "{")
tok = tok->next(); tok = tok->next();
tok = tok ? tok->next() : 0;
// Inspect the statements.. // Get return pointer..
unsigned int varid = 0; unsigned int varid = 0;
AllocType allocType = No; unsigned int indentlevel = 0;
while (tok) for (const Token *tok2 = tok; tok2; tok2 = tok2->next())
{ {
// variable declaration.. if (tok2->str() == "{")
if (Token::Match(tok, "%type% * %var% ;")) ++indentlevel;
else if (tok2->str() == "}")
{ {
tok = tok->tokAt(4); if (indentlevel <= 1)
continue; return No;
} }
if (Token::Match(tok2, "return %var% ;"))
if (varid == 0 && tok->varId() && Token::Match(tok, "%var% =")) {
if (indentlevel != 1)
return No;
varid = tok2->next()->varId();
break;
}
else if (tok2->str() == "return")
{
AllocType allocType = getAllocationType(tok2->next(), 0);
if (allocType != No)
return allocType;
allocType = getReallocationType(tok2->next(), 0);
if (allocType != No)
return allocType;
}
}
// Not returning pointer value..
if (varid == 0)
return No;
// Check if return pointer is allocated..
AllocType allocType = No;
while (0 != (tok = tok->next()))
{
if (Token::Match(tok, "%varid% =", varid))
{ {
varid = tok->varId();
allocType = getAllocationType(tok->tokAt(2), varid); allocType = getAllocationType(tok->tokAt(2), varid);
if (allocType == No) if (allocType == No)
return No; {
while (tok && tok->str() != ";") allocType = getReallocationType(tok->tokAt(2), varid);
tok = tok->next(); }
tok = tok ? tok->next() : 0; if (allocType != No)
continue;
}
if (tok->str() == ";")
{
tok = tok->next();
continue;
}
if (tok->str() == "return")
{
if (varid > 0 && Token::Match(tok->next(), "%varid% ;", varid))
return allocType; return allocType;
return getAllocationType(tok->next(), varid);
} }
if (tok->str() == "return")
return No; return allocType;
} }
return No; return No;
@ -587,7 +597,13 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<co
const Token *ftok = _tokenizer->getFunctionTokenByName(funcname.c_str()); const Token *ftok = _tokenizer->getFunctionTokenByName(funcname.c_str());
AllocType a = functionReturnType(ftok); AllocType a = functionReturnType(ftok);
if (a != No) if (a != No)
{
if (alloctype == No)
alloctype = a;
else if (alloctype != a)
alloctype = Many;
return "alloc"; return "alloc";
}
} }
// how many parameters is there in the function call? // how many parameters is there in the function call?

View File

@ -296,6 +296,7 @@ private:
TEST_CASE(allocfunc1); TEST_CASE(allocfunc1);
TEST_CASE(allocfunc2); TEST_CASE(allocfunc2);
TEST_CASE(allocfunc3); TEST_CASE(allocfunc3);
TEST_CASE(allocfunc4);
TEST_CASE(throw1); TEST_CASE(throw1);
TEST_CASE(throw2); TEST_CASE(throw2);
@ -1625,7 +1626,7 @@ private:
"{\n" "{\n"
" FILE *p = a();\n" " FILE *p = a();\n"
"}\n"); "}\n");
ASSERT_EQUALS(std::string("[test.cpp:8]: (error) Memory leak: p\n"), errout.str()); ASSERT_EQUALS(std::string("[test.cpp:8]: (error) Resource leak: p\n"), errout.str());
check("char *a()\n" check("char *a()\n"
"{\n" "{\n"
@ -1690,6 +1691,36 @@ private:
ASSERT_EQUALS(std::string("[test.cpp:8]: (error) Memory leak: p\n"), errout.str()); ASSERT_EQUALS(std::string("[test.cpp:8]: (error) Memory leak: p\n"), errout.str());
} }
void allocfunc4()
{
check("char* foo()\n"
"{\n"
" char *str = NULL;\n"
" str = realloc( str, 20 );\n"
" return str;\n"
"}\n"
"\n"
"void bar()\n"
"{\n"
" char *p = foo();\n"
"}\n");
ASSERT_EQUALS(std::string("[test.cpp:11]: (error) Memory leak: p\n"), errout.str());
check("char* foo()\n"
"{\n"
" char *str = NULL;\n"
" str = realloc( str, 20 );\n"
" return str;\n"
"}\n"
"\n"
"void bar()\n"
"{\n"
" char *p = foo();\n"
" delete p;\n"
"}\n");
ASSERT_EQUALS(std::string("[test.cpp:11]: (error) Mismatching allocation and deallocation: p\n"), errout.str());
}