diff --git a/cfg/gtk.cfg b/cfg/gtk.cfg index 49c89473e..43668d8d0 100644 --- a/cfg/gtk.cfg +++ b/cfg/gtk.cfg @@ -18,7 +18,7 @@ g_register_data - + false diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index d1636abd6..239b28d46 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -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 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::liststr())) { + } 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::listprevious(), "&|(") && 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::liststr()) != 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; } diff --git a/lib/checkmemoryleak.h b/lib/checkmemoryleak.h index 2c43ecc3c..7ed93f5cc 100644 --- a/lib/checkmemoryleak.h +++ b/lib/checkmemoryleak.h @@ -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(); diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 1433420a6..c1a991739 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -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() {