CheckMemoryLeak: use library while checking whitelist functions
This commit is contained in:
parent
6ac9e180e0
commit
0dd227419d
|
@ -18,7 +18,7 @@
|
||||||
<use>g_register_data</use>
|
<use>g_register_data</use>
|
||||||
</memory>
|
</memory>
|
||||||
|
|
||||||
<function name="g_strcmp">
|
<function name="g_strcmp0">
|
||||||
<leak-ignore/>
|
<leak-ignore/>
|
||||||
<noreturn>false</noreturn>
|
<noreturn>false</noreturn>
|
||||||
</function>
|
</function>
|
||||||
|
|
|
@ -558,10 +558,18 @@ bool CheckMemoryLeakInFunction::test_white_list(const std::string &funcname)
|
||||||
funcname));
|
funcname));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CheckMemoryLeakInFunction::test_white_list_with_lib(const std::string &funcname, const Settings *settings)
|
||||||
|
{
|
||||||
|
return (std::binary_search(call_func_white_list,
|
||||||
|
call_func_white_list+sizeof(call_func_white_list) / sizeof(call_func_white_list[0]),
|
||||||
|
funcname) || (settings->library.leakignore.find(funcname) != settings->library.leakignore.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool &allocpar, unsigned int sz)
|
const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool &allocpar, unsigned int sz)
|
||||||
{
|
{
|
||||||
if (test_white_list(tok->str()) ||
|
if (test_white_list_with_lib(tok->str(), _settings)) {
|
||||||
(_settings->library.leakignore.find(tok->str()) != _settings->library.leakignore.end())) {
|
|
||||||
if (tok->str() == "asprintf" ||
|
if (tok->str() == "asprintf" ||
|
||||||
tok->str() == "delete" ||
|
tok->str() == "delete" ||
|
||||||
tok->str() == "fclose" ||
|
tok->str() == "fclose" ||
|
||||||
|
@ -1039,7 +1047,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
|
||||||
dep = true;
|
dep = true;
|
||||||
} else if (Token::Match(tok2, "! %varid%", varid)) {
|
} else if (Token::Match(tok2, "! %varid%", varid)) {
|
||||||
dep = true;
|
dep = true;
|
||||||
} else if (Token::Match(tok2, "%var% (") && !test_white_list(tok2->str())) {
|
} else if (Token::Match(tok2, "%var% (") && !test_white_list_with_lib(tok2->str(), _settings)) {
|
||||||
bool use = false;
|
bool use = false;
|
||||||
for (const Token *tok3 = tok2->tokAt(2); tok3; tok3 = tok3->nextArgument()) {
|
for (const Token *tok3 = tok2->tokAt(2); tok3; tok3 = tok3->nextArgument()) {
|
||||||
if (Token::Match(tok3->previous(), "(|, &| %varid% ,|)", varid)) {
|
if (Token::Match(tok3->previous(), "(|, &| %varid% ,|)", varid)) {
|
||||||
|
@ -1214,7 +1222,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
|
||||||
if (!Token::Match(tok2->previous(), "&|(") &&
|
if (!Token::Match(tok2->previous(), "&|(") &&
|
||||||
tok2->strAt(1) == "[") {
|
tok2->strAt(1) == "[") {
|
||||||
} else if (f.empty() ||
|
} else if (f.empty() ||
|
||||||
!test_white_list(f.top()->str()) ||
|
!test_white_list_with_lib(f.top()->str(), _settings) ||
|
||||||
getDeallocationType(f.top(),varid)) {
|
getDeallocationType(f.top(),varid)) {
|
||||||
use = true;
|
use = true;
|
||||||
}
|
}
|
||||||
|
@ -1300,7 +1308,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
|
||||||
if (noreturn.find(tok->str()) != noreturn.end())
|
if (noreturn.find(tok->str()) != noreturn.end())
|
||||||
addtoken(&rettail, tok, "exit");
|
addtoken(&rettail, tok, "exit");
|
||||||
|
|
||||||
else if (!test_white_list(tok->str())) {
|
else if (!test_white_list_with_lib(tok->str(), _settings)) {
|
||||||
const Token* const end2 = tok->linkAt(1);
|
const Token* const end2 = tok->linkAt(1);
|
||||||
for (const Token *tok2 = tok->tokAt(2); tok2 != end2; tok2 = tok2->next()) {
|
for (const Token *tok2 = tok->tokAt(2); tok2 != end2; tok2 = tok2->next()) {
|
||||||
if (tok2->varId() == varid) {
|
if (tok2->varId() == varid) {
|
||||||
|
@ -2405,7 +2413,7 @@ void CheckMemoryLeakInClass::variable(const Scope *scope, const Token *tokVarnam
|
||||||
|
|
||||||
// Function call .. possible deallocation
|
// Function call .. possible deallocation
|
||||||
else if (Token::Match(tok->previous(), "[{};] %var% (")) {
|
else if (Token::Match(tok->previous(), "[{};] %var% (")) {
|
||||||
if (!CheckMemoryLeakInFunction::test_white_list(tok->str())) {
|
if (!CheckMemoryLeakInFunction::test_white_list_with_lib(tok->str(), _settings)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2721,7 +2729,7 @@ void CheckMemoryLeakNoVar::check()
|
||||||
functionName == "fclose" ||
|
functionName == "fclose" ||
|
||||||
functionName == "realloc")
|
functionName == "realloc")
|
||||||
break;
|
break;
|
||||||
if (CheckMemoryLeakInFunction::test_white_list(functionName)) {
|
if (CheckMemoryLeakInFunction::test_white_list_with_lib(functionName, _settings)) {
|
||||||
functionCallLeak(tok2, tok2->strAt(1), functionName);
|
functionCallLeak(tok2, tok2->strAt(1), functionName);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,6 +204,7 @@ public:
|
||||||
|
|
||||||
/** @brief Unit testing : testing the white list */
|
/** @brief Unit testing : testing the white list */
|
||||||
static bool test_white_list(const std::string &funcname);
|
static bool test_white_list(const std::string &funcname);
|
||||||
|
static bool test_white_list_with_lib(const std::string &funcname, const Settings *settings);
|
||||||
|
|
||||||
/** @brief Perform checking */
|
/** @brief Perform checking */
|
||||||
void check();
|
void check();
|
||||||
|
|
|
@ -6102,6 +6102,9 @@ private:
|
||||||
Settings settings;
|
Settings settings;
|
||||||
settings.standards.posix = true;
|
settings.standards.posix = true;
|
||||||
|
|
||||||
|
LOAD_LIB("gtk.cfg");
|
||||||
|
settings.library = _lib;
|
||||||
|
|
||||||
// Add some test allocation functions to the library.
|
// Add some test allocation functions to the library.
|
||||||
// When not run as a unit test, these are read from
|
// When not run as a unit test, these are read from
|
||||||
// an XML file (e.g. cfg/posix.cfg).
|
// an XML file (e.g. cfg/posix.cfg).
|
||||||
|
@ -6136,17 +6139,30 @@ private:
|
||||||
" strcpy(a, strdup(p));\n"
|
" strcpy(a, strdup(p));\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (error) Allocation with strdup, strcpy doesn't release it.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:2]: (error) Allocation with strdup, strcpy doesn't release it.\n", errout.str());
|
||||||
|
check("void x() {\n"
|
||||||
|
" g_strcpy(a, g_strdup(p));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (error) Allocation with g_strdup, g_strcpy doesn't release it.\n", errout.str());
|
||||||
|
|
||||||
check("char *x() {\n"
|
check("char *x() {\n"
|
||||||
" char *ret = strcpy(malloc(10), \"abc\");\n"
|
" char *ret = strcpy(malloc(10), \"abc\");\n"
|
||||||
" return ret;\n"
|
" return ret;\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
check("gchar *x() {\n"
|
||||||
|
" gchar *ret = g_strcpy(g_malloc(10), \"abc\");\n"
|
||||||
|
" return ret;\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("void x() {\n"
|
check("void x() {\n"
|
||||||
" free(malloc(10));\n"
|
" free(malloc(10));\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
check("void x() {\n"
|
||||||
|
" g_free(g_malloc(10));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// user function..
|
// user function..
|
||||||
check("void set_error(const char *msg) {\n"
|
check("void set_error(const char *msg) {\n"
|
||||||
|
@ -6156,6 +6172,13 @@ private:
|
||||||
" set_error(strdup(p));\n"
|
" set_error(strdup(p));\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:5]: (error) Allocation with strdup, set_error doesn't release it.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:5]: (error) Allocation with strdup, set_error doesn't release it.\n", errout.str());
|
||||||
|
check("void set_error(const char *msg) {\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"void x() {\n"
|
||||||
|
" set_error(g_strdup(p));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:5]: (error) Allocation with g_strdup, set_error doesn't release it.\n", errout.str());
|
||||||
|
|
||||||
check("void f()\n"
|
check("void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
|
@ -6170,18 +6193,33 @@ private:
|
||||||
" if(TRUE || strcmp(strdup(a), b));\n"
|
" if(TRUE || strcmp(strdup(a), b));\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (error) Allocation with strdup, strcmp doesn't release it.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (error) Allocation with strdup, strcmp doesn't release it.\n", errout.str());
|
||||||
|
check("void f()\n"
|
||||||
|
"{\n"
|
||||||
|
" if(TRUE || g_strcmp0(g_strdup(a), b));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Allocation with g_strdup, g_strcmp0 doesn't release it.\n", errout.str());
|
||||||
|
|
||||||
check("void f()\n"
|
check("void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" if(!strcmp(strdup(a), b) == 0);\n"
|
" if(!strcmp(strdup(a), b) == 0);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (error) Allocation with strdup, strcmp doesn't release it.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (error) Allocation with strdup, strcmp doesn't release it.\n", errout.str());
|
||||||
|
check("void f()\n"
|
||||||
|
"{\n"
|
||||||
|
" if(!g_strcmp0(g_strdup(a), b) == 0);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Allocation with g_strdup, g_strcmp0 doesn't release it.\n", errout.str());
|
||||||
|
|
||||||
check("void f()\n"
|
check("void f()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" 42, strcmp(strdup(a), b);\n"
|
" 42, strcmp(strdup(a), b);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("[test.cpp:3]: (error) Allocation with strdup, strcmp doesn't release it.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (error) Allocation with strdup, strcmp doesn't release it.\n", errout.str());
|
||||||
|
check("void f()\n"
|
||||||
|
"{\n"
|
||||||
|
" 42, g_strcmp0(g_strdup(a), b);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Allocation with g_strdup, g_strcmp0 doesn't release it.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void missingAssignment() {
|
void missingAssignment() {
|
||||||
|
|
Loading…
Reference in New Issue