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 @@
-
+
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() {