Fixed #1648 (mismatch allocate and deallocate calls.)
This commit is contained in:
parent
7c52c8683d
commit
d7118c4d36
|
@ -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?
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue