Merge pull request #234 from scriptum/rpg-use-whitelist-from-library
CheckMemoryLeak: use library while checking whitelist functions
This commit is contained in:
commit
3c6bfac89c
|
@ -18,7 +18,7 @@
|
|||
<use>g_register_data</use>
|
||||
</memory>
|
||||
|
||||
<function name="g_strcmp">
|
||||
<function name="g_strcmp0">
|
||||
<leak-ignore/>
|
||||
<noreturn>false</noreturn>
|
||||
</function>
|
||||
|
|
|
@ -558,10 +558,18 @@ bool CheckMemoryLeakInFunction::test_white_list(const std::string &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)
|
||||
{
|
||||
if (test_white_list(tok->str()) ||
|
||||
(_settings->library.leakignore.find(tok->str()) != _settings->library.leakignore.end())) {
|
||||
if (test_white_list_with_lib(tok->str(), _settings)) {
|
||||
if (tok->str() == "asprintf" ||
|
||||
tok->str() == "delete" ||
|
||||
tok->str() == "fclose" ||
|
||||
|
@ -1039,7 +1047,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
|
|||
dep = true;
|
||||
} else if (Token::Match(tok2, "! %varid%", varid)) {
|
||||
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;
|
||||
for (const Token *tok3 = tok2->tokAt(2); tok3; tok3 = tok3->nextArgument()) {
|
||||
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(), "&|(") &&
|
||||
tok2->strAt(1) == "[") {
|
||||
} else if (f.empty() ||
|
||||
!test_white_list(f.top()->str()) ||
|
||||
!test_white_list_with_lib(f.top()->str(), _settings) ||
|
||||
getDeallocationType(f.top(),varid)) {
|
||||
use = true;
|
||||
}
|
||||
|
@ -1300,7 +1308,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
|
|||
if (noreturn.find(tok->str()) != noreturn.end())
|
||||
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);
|
||||
for (const Token *tok2 = tok->tokAt(2); tok2 != end2; tok2 = tok2->next()) {
|
||||
if (tok2->varId() == varid) {
|
||||
|
@ -2405,7 +2413,7 @@ void CheckMemoryLeakInClass::variable(const Scope *scope, const Token *tokVarnam
|
|||
|
||||
// Function call .. possible deallocation
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -2721,7 +2729,7 @@ void CheckMemoryLeakNoVar::check()
|
|||
functionName == "fclose" ||
|
||||
functionName == "realloc")
|
||||
break;
|
||||
if (CheckMemoryLeakInFunction::test_white_list(functionName)) {
|
||||
if (CheckMemoryLeakInFunction::test_white_list_with_lib(functionName, _settings)) {
|
||||
functionCallLeak(tok2, tok2->strAt(1), functionName);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -204,6 +204,7 @@ public:
|
|||
|
||||
/** @brief Unit testing : testing the white list */
|
||||
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 */
|
||||
void check();
|
||||
|
|
|
@ -6102,6 +6102,9 @@ private:
|
|||
Settings settings;
|
||||
settings.standards.posix = true;
|
||||
|
||||
LOAD_LIB("gtk.cfg");
|
||||
settings.library = _lib;
|
||||
|
||||
// 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).
|
||||
|
@ -6136,17 +6139,30 @@ private:
|
|||
" strcpy(a, strdup(p));\n"
|
||||
"}");
|
||||
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"
|
||||
" char *ret = strcpy(malloc(10), \"abc\");\n"
|
||||
" return ret;\n"
|
||||
"}");
|
||||
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"
|
||||
" free(malloc(10));\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
check("void x() {\n"
|
||||
" g_free(g_malloc(10));\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// user function..
|
||||
check("void set_error(const char *msg) {\n"
|
||||
|
@ -6156,6 +6172,13 @@ private:
|
|||
" set_error(strdup(p));\n"
|
||||
"}");
|
||||
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"
|
||||
"{\n"
|
||||
|
@ -6170,18 +6193,33 @@ private:
|
|||
" if(TRUE || strcmp(strdup(a), b));\n"
|
||||
"}");
|
||||
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"
|
||||
"{\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());
|
||||
|
||||
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"
|
||||
"{\n"
|
||||
" 42, strcmp(strdup(a), b);\n"
|
||||
"}");
|
||||
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() {
|
||||
|
|
Loading…
Reference in New Issue