diff --git a/cfg/gtk.cfg b/cfg/gtk.cfg
index 4226b4666..49c89473e 100644
--- a/cfg/gtk.cfg
+++ b/cfg/gtk.cfg
@@ -23,6 +23,17 @@
false
+
+
+ false
+
+
+
+
+
+
+
+
true
diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp
index bc709a7d7..84aa75651 100644
--- a/test/testmemleak.cpp
+++ b/test/testmemleak.cpp
@@ -130,7 +130,11 @@ private:
Settings settings1;
if (!settings)
+ {
+ LOAD_LIB("gtk.cfg");
+ settings1.library = _lib;
settings = &settings1;
+ }
// Tokenize..
Tokenizer tokenizer(settings, this);
@@ -936,6 +940,24 @@ private:
" free(s);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("void Fred::aaa()\n"
+ "{ }\n"
+ "\n"
+ "void Fred::foo()\n"
+ "{\n"
+ " gchar *s = NULL;\n"
+ " if (a)\n"
+ " s = g_malloc(10);\n"
+ " else if (b)\n"
+ " s = g_malloc(10);\n"
+ " else\n"
+ " f();\n"
+ " g(s);\n"
+ " if (c)\n"
+ " h(s);\n"
+ " g_free(s);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
@@ -1019,6 +1041,14 @@ private:
" return 123;\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("int f()\n"
+ "{\n"
+ " static gchar *s = 0;\n"
+ " g_free(s);\n"
+ " s = g_malloc(100);\n"
+ " return 123;\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void externvar() {
@@ -1122,6 +1152,16 @@ private:
" free(s);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("void f()\n"
+ "{\n"
+ " gchar *s;\n"
+ " bool b = true;\n"
+ " if (b && (s = g_malloc(256)))\n"
+ " ;\n"
+ " if (b)\n"
+ " g_free(s);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void if7() {
@@ -1156,6 +1196,21 @@ private:
" free(c);\n"
"}");
ASSERT_EQUALS("[test.cpp:11]: (error) Memory leak: c\n", errout.str());
+ check("static void f(int i)\n"
+ "{\n"
+ " gchar *c = g_malloc(50);\n"
+ " if (i == 1)\n"
+ " {\n"
+ " g_free(c);\n"
+ " return;\n"
+ " }\n"
+ " if (i == 2)\n"
+ " {\n"
+ " return;\n"
+ " }\n"
+ " g_free(c);\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:11]: (error) Memory leak: c\n", errout.str());
}
void if9() {
@@ -1501,6 +1556,14 @@ private:
" free(buf);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("void f(gchar *buf)\n"
+ "{\n"
+ " int i;\n"
+ " buf = g_malloc(3);\n"
+ " buf[i] = 0;\n"
+ " g_free(buf);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
@@ -1665,6 +1728,18 @@ private:
" free(p);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static void foo(gchar *a, gchar *b)\n"
+ "{\n"
+ " g_free(a);\n"
+ " g_free(b);\n"
+ "}\n"
+ "static void f()\n"
+ "{\n"
+ " gchar *p = g_malloc(100);\n"
+ " foo(p);\n"
+ " g_free(p);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void func15() {
@@ -1678,6 +1753,16 @@ private:
" free(p);\n"
"}");
ASSERT_EQUALS("[test.cpp:7]: (error) Memory leak: p\n", errout.str());
+ check("static void a()\n"
+ "{ return true; }\n"
+ "\n"
+ "static void b()\n"
+ "{\n"
+ " gchar *p = g_malloc(100);\n"
+ " if (a()) return;\n" // <- memory leak
+ " g_free(p);\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:7]: (error) Memory leak: p\n", errout.str());
}
void func16() {
@@ -1750,6 +1835,28 @@ private:
" free_pointers(1, p);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static void free_pointers(int arg_count, ...)\n"
+ "{\n"
+ " va_list a;\n"
+ " va_start(a, arg_count);\n"
+ " for (int i = 0; i < arg_count; i++)\n"
+ " {\n"
+ " g_free(va_arg(a, void *));\n"
+ " }\n"
+ " va_end(a);\n"
+ "}\n"
+ "\n"
+ "static gchar* foo()\n"
+ "{\n"
+ " return g_strdup(\"\");\n"
+ "}\n"
+ "\n"
+ "static void bar()\n"
+ "{\n"
+ " int *p = g_malloc(16);\n"
+ " free_pointers(1, p);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void func19() {
@@ -1764,6 +1871,16 @@ private:
" free(p);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("bool a(int *p) {\n"
+ " return p;\n"
+ "}\n"
+ "\n"
+ "void b() {\n"
+ " int *p = g_malloc(16);\n"
+ " if (!a(p)) return;\n"
+ " g_free(p);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void func20() {
@@ -2377,6 +2494,16 @@ private:
" free(p);\n"
"}");
ASSERT_EQUALS(std::string(""), errout.str());
+ check("gchar *a()\n"
+ "{\n"
+ " return g_malloc(10);\n"
+ "}\n"
+ "static void b()\n"
+ "{\n"
+ " gchar *p = a();\n"
+ " g_free(p);\n"
+ "}");
+ ASSERT_EQUALS(std::string(""), errout.str());
}
void allocfunc3() {
@@ -2488,6 +2615,20 @@ private:
" free(tmp);\n"
"}");
ASSERT_EQUALS(std::string(""), errout.str());
+ check("void foo(gchar **str)\n"
+ "{\n"
+ " g_free(*str);\n"
+ " *str = g_malloc(20);\n"
+ "}\n"
+ "\n"
+ "void bar()\n"
+ "{\n"
+ " gchar *tmp = g_malloc(10);\n"
+ " foo(&tmp);\n"
+ " foo(&tmp);\n"
+ " g_free(tmp);\n"
+ "}");
+ ASSERT_EQUALS(std::string(""), errout.str());
//#ticket 1789: getcode other function:
check("void foo(char **str)\n"
@@ -2526,6 +2667,22 @@ private:
" free(expr);\n"
"}");
ASSERT_EQUALS(std::string(""), errout.str());
+ check("static FILE* data()\n"
+ "{\n"
+ " return fopen(\"data.txt\",\"rt\");\n"
+ "}\n"
+ "\n"
+ "static void foo()\n"
+ "{\n"
+ " gchar* expr;\n"
+ " func(&expr);\n"
+ "\n"
+ " FILE *f = data();\n"
+ " fclose(f);\n"
+ "\n"
+ " g_free(expr);\n"
+ "}");
+ ASSERT_EQUALS(std::string(""), errout.str());
}
@@ -2709,6 +2866,25 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:12]: (error) Memory leak: s2\n", errout.str());
+ check("void f()\n"
+ "{\n"
+ " struct s_t s1;\n"
+ " struct s_t cont *p = &s1;\n"
+ " struct s_t *s2;\n"
+ "\n"
+ " memset(p, 0, sizeof(*p));\n"
+ "\n"
+ " s2 = (struct s_t *) g_malloc(sizeof(*s2));\n"
+ "\n"
+ " if (s2->value != 0)\n"
+ " return;\n"
+ "\n"
+ " g_free(s2);\n"
+ "\n"
+ " return;\n"
+ "}");
+
+ ASSERT_EQUALS("[test.cpp:12]: (error) Memory leak: s2\n", errout.str());
}
@@ -2887,6 +3063,14 @@ private:
" free(a);\n"
"}");
+ ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: a\n", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " gchar *a = (gchar *)g_malloc(10);\n"
+ " a = 0;\n"
+ " g_free(a);\n"
+ "}");
+
ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: a\n", errout.str());
check("void foo()\n"
@@ -2896,6 +3080,14 @@ private:
" free(p);\n"
"}");
+ ASSERT_EQUALS("", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " gchar *a = (gchar *)g_malloc(10);\n"
+ " gchar *p = a;\n"
+ " g_free(p);\n"
+ "}");
+
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
@@ -2905,6 +3097,14 @@ private:
" free(p);\n"
"}");
+ ASSERT_EQUALS("", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " gchar *a = (gchar *)g_malloc(10);\n"
+ " gchar *p = a + 1;\n"
+ " g_free(p);\n"
+ "}");
+
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
@@ -2914,6 +3114,14 @@ private:
" free(a - 10);\n"
"}");
+ ASSERT_EQUALS("", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " gchar *a = (gchar *)g_malloc(10);\n"
+ " a += 10;\n"
+ " g_free(a - 10);\n"
+ "}");
+
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
@@ -2923,6 +3131,14 @@ private:
" free(a - 10);\n"
"}");
+ ASSERT_EQUALS("", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " gchar *a = (gchar *)g_malloc(10);\n"
+ " a = (void *)a + 10;\n"
+ " g_free(a - 10);\n"
+ "}");
+
ASSERT_EQUALS("", errout.str());
check("void foo()\n"
@@ -2956,6 +3172,16 @@ private:
" free(p);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " gchar *p = g_malloc(100);\n"
+ " {\n"
+ " gchar *p = 0;\n"
+ " delete p;\n"
+ " }\n"
+ " g_free(p);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void cast1() {
@@ -2965,6 +3191,12 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: a\n", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " char *a = reinterpret_cast(g_malloc(10));\n"
+ "}");
+
+ ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: a\n", errout.str());
}
@@ -3003,6 +3235,13 @@ private:
" foo(&str);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("void f()\n"
+ "{\n"
+ " gchar *str;\n"
+ " g_free(str);\n"
+ " foo(&str);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
check("void foo()\n"
"{\n"
@@ -3012,6 +3251,14 @@ private:
" f2(str);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " gchar *str = 0;\n"
+ " g_free(str);\n"
+ " f1(&str);\n"
+ " f2(str);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
// Dereferencing the freed pointer is not ok..
check("void foo()\n"
@@ -3022,6 +3269,14 @@ private:
"}");
TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released\n",
"", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " gchar *str = g_malloc(10);\n"
+ " g_free(str);\n"
+ " gchar c = *str;\n"
+ "}");
+ TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released\n",
+ "", errout.str());
check("void foo()\n"
"{\n"
@@ -3030,6 +3285,13 @@ private:
" char c = str[10];\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released\n", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " gchar *str = g_malloc(10);\n"
+ " g_free(str);\n"
+ " gchar c = str[10];\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released\n", errout.str());
check("void foo()\n"
"{\n"
@@ -3038,6 +3300,13 @@ private:
" str[10] = 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released\n", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " gchar *str = g_malloc(10);\n"
+ " g_free(str);\n"
+ " str[10] = 0;\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released\n", errout.str());
check("void foo() {\n"
" char *str = malloc(10);\n"
@@ -3045,6 +3314,12 @@ private:
" strcpy(str, p);\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Dereferencing 'str' after it is deallocated / released\n", errout.str());
+ check("void foo() {\n"
+ " gchar *str = g_malloc(10);\n"
+ " g_free(str);\n"
+ " g_strcpy(str, p);\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:4]: (error) Dereferencing 'str' after it is deallocated / released\n", errout.str());
check("void foo(int x) {\n"
" char *str = malloc(10);\n"
@@ -3052,6 +3327,12 @@ private:
" assert(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("void foo(int x) {\n"
+ " gchar *str = g_malloc(10);\n"
+ " g_free(str);\n"
+ " assert(x);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void dealloc_use_2() {
@@ -3061,6 +3342,11 @@ private:
" strcpy(a, s=b());\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("void f(gchar *s) {\n"
+ " g_free(s);\n"
+ " g_strcpy(a, s=b());\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void dealloc_use_3() {
@@ -3089,6 +3375,13 @@ private:
" free(str);\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Deallocating a deallocated pointer: str\n", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " gchar *str = g_malloc(100);\n"
+ " g_free(str);\n"
+ " g_free(str);\n"
+ "}");
+ ASSERT_EQUALS("[test.cpp:5]: (error) Deallocating a deallocated pointer: str\n", errout.str());
}
void freefree2() {
@@ -3110,6 +3403,14 @@ private:
" free(p);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " gchar *p = g_malloc(10);\n"
+ " g_free(p);\n"
+ " bar(&p);\n"
+ " g_free(p);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void strcpy_result_assignment() {
@@ -3119,6 +3420,12 @@ private:
" char *p2 = strcpy(p1, \"a\");\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " char *p1 = g_malloc(10);\n"
+ " char *p2 = g_strcpy(p1, \"a\");\n"
+ "}");
+ TODO_ASSERT_EQUALS("", "[test.cpp:5]: (error) Memory leak: p1\n", errout.str());
}
void strcat_result_assignment() {
@@ -3131,6 +3438,15 @@ private:
" return 0;\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " gchar *p = g_malloc(10);\n"
+ " p[0] = 0;\n"
+ " p = g_strcat( p, \"a\" );\n"
+ " g_free( p );\n"
+ " return 0;\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
@@ -3152,6 +3468,12 @@ private:
" free(p);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (error) The given size 3 is mismatching\n", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " int *p = g_malloc(3);\n"
+ " g_free(p);\n"
+ "}\n");
+ TODO_ASSERT_EQUALS("[test.cpp:3]: (error) The given size 3 is mismatching\n", "", errout.str());
}
@@ -3217,6 +3539,20 @@ private:
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static void foo()\n"
+ "{\n"
+ " gchar *p = NULL;\n"
+ "\n"
+ " if( a )\n"
+ " p = g_malloc(100);\n"
+ "\n"
+ " if( a )\n"
+ " {\n"
+ " FREENULL(p);\n"
+ " FREENULL();\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
@@ -3727,6 +4063,19 @@ private:
" free(sym);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("void foo()\n"
+ "{\n"
+ " void *sym = ( {\n"
+ " void *__ptr = g_malloc(100);\n"
+ " if(!__ptr && 100 != 0)\n"
+ " {\n"
+ " g_exit(1);\n"
+ " }\n"
+ " __ptr;\n"
+ " } );\n"
+ " g_free(sym);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void knownFunctions() {
@@ -4038,6 +4387,25 @@ private:
" free(str1);\n"
"}");
ASSERT_EQUALS("[test.cpp:17]: (error) Mismatching allocation and deallocation: Fred::str1\n", errout.str());
+ check("class Fred\n"
+ "{\n"
+ "private:\n"
+ " gchar *str1;\n"
+ "public:\n"
+ " Fred();\n"
+ " ~Fred();\n"
+ "};\n"
+ "\n"
+ "Fred::Fred()\n"
+ "{\n"
+ " str1 = new char[10];\n"
+ "}\n"
+ "\n"
+ "Fred::~Fred()\n"
+ "{\n"
+ " g_free(str1);\n"
+ "}");
+ TODO_ASSERT_EQUALS("[test.cpp:17]: (error) Mismatching allocation and deallocation: Fred::str1\n", "", errout.str());
check("class Fred\n"
"{\n"
@@ -4054,6 +4422,21 @@ private:
" }\n"
"};");
ASSERT_EQUALS("[test.cpp:12]: (error) Mismatching allocation and deallocation: Fred::str1\n", errout.str());
+ check("class Fred\n"
+ "{\n"
+ "private:\n"
+ " char *str1;\n"
+ "public:\n"
+ " Fred()\n"
+ " {\n"
+ " str1 = new char[10];\n"
+ " }\n"
+ " ~Fred()\n"
+ " {\n"
+ " g_free(str1);\n"
+ " }\n"
+ "};");
+ TODO_ASSERT_EQUALS("[test.cpp:12]: (error) Mismatching allocation and deallocation: Fred::str1\n", "", errout.str());
}
void class3() {
@@ -4521,6 +4904,16 @@ private:
"A::A()\n"
"{ p = malloc(sizeof(int)*10); }");
ASSERT_EQUALS("", errout.str());
+ check("class A\n"
+ "{\n"
+ " int *p;\n"
+ "public:\n"
+ " A();\n"
+ " ~A() { g_free(p); }\n"
+ "};\n"
+ "A::A()\n"
+ "{ p = g_malloc(sizeof(int)*10); }");
+ ASSERT_EQUALS("", errout.str());
check("class A\n"
"{\n"
@@ -4531,6 +4924,15 @@ private:
" ~A() { free(p); }\n"
"};");
ASSERT_EQUALS("", errout.str());
+ check("class A\n"
+ "{\n"
+ " int *p;\n"
+ "public:\n"
+ " A()\n"
+ " { p = g_malloc(sizeof(int)*10); }\n"
+ " ~A() { g_free(p); }\n"
+ "};");
+ ASSERT_EQUALS("", errout.str());
}
void class16() {
@@ -4998,6 +5400,17 @@ private:
" { s = malloc(100); }\n"
"};");
ASSERT_EQUALS("[test.cpp:9]: (warning) Possible leak in public function. The pointer 's' is not deallocated before it is allocated.\n", errout.str());
+ check("class Fred\n"
+ "{\n"
+ "private:\n"
+ " gchar *s;\n"
+ "public:\n"
+ " Fred() { s = 0; }\n"
+ " ~Fred() { g_free(s); }\n"
+ " void xy()\n"
+ " { s = g_malloc(100); }\n"
+ "};");
+ TODO_ASSERT_EQUALS("[test.cpp:9]: (warning) Possible leak in public function. The pointer 's' is not deallocated before it is allocated.\n", "", errout.str());
check("class Fred\n"
"{\n"
@@ -5010,6 +5423,17 @@ private:
" char *s;\n"
"};");
ASSERT_EQUALS("[test.cpp:7]: (warning) Possible leak in public function. The pointer 's' is not deallocated before it is allocated.\n", errout.str());
+ check("class Fred\n"
+ "{\n"
+ "public:\n"
+ " Fred() { s = 0; }\n"
+ " ~Fred() { g_free(s); }\n"
+ " void xy()\n"
+ " { s = g_malloc(100); }\n"
+ "private:\n"
+ " char *s;\n"
+ "};");
+ TODO_ASSERT_EQUALS("[test.cpp:7]: (warning) Possible leak in public function. The pointer 's' is not deallocated before it is allocated.\n", "", errout.str());
}
void func2() {
@@ -5024,6 +5448,17 @@ private:
" { s = malloc(100); }\n"
"};");
ASSERT_EQUALS("[test.cpp:9]: (warning) Possible leak in public function. The pointer 's' is not deallocated before it is allocated.\n", errout.str());
+ check("class Fred\n"
+ "{\n"
+ "private:\n"
+ " gchar *s;\n"
+ "public:\n"
+ " Fred() { s = 0; }\n"
+ " ~Fred() { g_free(s); }\n"
+ " const Fred & operator = (const Fred &f)\n"
+ " { s = g_malloc(100); }\n"
+ "};");
+ TODO_ASSERT_EQUALS("[test.cpp:9]: (warning) Possible leak in public function. The pointer 's' is not deallocated before it is allocated.\n", "", errout.str());
}
};
@@ -5108,6 +5543,13 @@ private:
" free(abc);\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: abc.a\n", errout.str());
+ check("static void foo()\n"
+ "{\n"
+ " struct ABC *abc = g_malloc(sizeof(struct ABC));\n"
+ " abc->a = g_malloc(10);\n"
+ " g_free(abc);\n"
+ "}");
+ TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: abc.a\n", "", errout.str());
check("static void foo()\n"
"{\n"
@@ -5115,6 +5557,12 @@ private:
" abc->a = malloc(10);\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: abc.a\n", errout.str());
+ check("static void foo()\n"
+ "{\n"
+ " struct ABC *abc = g_malloc(sizeof(struct ABC));\n"
+ " abc->a = g_malloc(10);\n"
+ "}");
+ TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: abc.a\n", "", errout.str());
check("static ABC * foo()\n"
"{\n"
@@ -5128,6 +5576,18 @@ private:
" return abc;\n"
"}");
ASSERT_EQUALS("[test.cpp:8]: (error) Memory leak: abc.a\n", errout.str());
+ check("static ABC * foo()\n"
+ "{\n"
+ " ABC *abc = g_malloc(sizeof(ABC));\n"
+ " abc->a = g_malloc(10);\n"
+ " abc->b = g_malloc(10);\n"
+ " if (abc->b == 0)\n"
+ " {\n"
+ " return 0;\n"
+ " }\n"
+ " return abc;\n"
+ "}");
+ TODO_ASSERT_EQUALS("[test.cpp:8]: (error) Memory leak: abc.a\n", "", errout.str());
check("static void foo(int a)\n"
"{\n"
@@ -5140,6 +5600,17 @@ private:
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:10]: (error) Memory leak: abc.a\n", errout.str());
+ check("static void foo(int a)\n"
+ "{\n"
+ " ABC *abc = g_malloc(sizeof(ABC));\n"
+ " abc->a = g_malloc(10);\n"
+ " if (a == 1)\n"
+ " {\n"
+ " g_free(abc->a);\n"
+ " return;\n"
+ " }\n"
+ "}");
+ TODO_ASSERT_EQUALS("[test.cpp:10]: (error) Memory leak: abc.a\n", "", errout.str());
}
void goto_() {
@@ -5156,6 +5627,19 @@ private:
" free(abc);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static void foo()\n"
+ "{\n"
+ " struct ABC *abc = g_malloc(sizeof(struct ABC));\n"
+ " abc->a = g_malloc(10);\n"
+ " if (abc->a)\n"
+ " { goto out; }\n"
+ " g_free(abc);\n"
+ " return;\n"
+ "out:\n"
+ " g_free(abc->a);\n"
+ " g_free(abc);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void ret1() {
@@ -5166,12 +5650,24 @@ private:
" return abc;\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static ABC * foo()\n"
+ "{\n"
+ " struct ABC *abc = g_malloc(sizeof(struct ABC));\n"
+ " abc->a = g_malloc(10);\n"
+ " return abc;\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
check("static void foo(struct ABC *abc)\n"
"{\n"
" abc->a = malloc(10);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static void foo(struct ABC *abc)\n"
+ "{\n"
+ " abc->a = g_malloc(10);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void ret2() {
@@ -5182,6 +5678,13 @@ private:
" return &abc->self;\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static ABC * foo()\n"
+ "{\n"
+ " struct ABC *abc = g_malloc(sizeof(struct ABC));\n"
+ " abc->a = g_malloc(10);\n"
+ " return &abc->self;\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void assign1() {
@@ -5191,6 +5694,12 @@ private:
" abc->a = malloc(10);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static void foo()\n"
+ "{\n"
+ " struct ABC *abc = abc1;\n"
+ " abc->a = g_malloc(10);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
check("static void foo()\n"
"{\n"
@@ -5199,6 +5708,13 @@ private:
" abc->a = malloc(10);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static void foo()\n"
+ "{\n"
+ " struct ABC *abc;\n"
+ " abc1 = abc = g_malloc(sizeof(ABC));\n"
+ " abc->a = g_malloc(10);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
check("static void foo()\n"
@@ -5209,6 +5725,14 @@ private:
" back = ptr;\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static void foo()\n"
+ "{\n"
+ " struct msn_entry *ptr;\n"
+ " ptr = g_malloc(sizeof(struct msn_entry));\n"
+ " ptr->msn = g_malloc(100);\n"
+ " back = ptr;\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
@@ -5218,6 +5742,11 @@ private:
" abc->a = abc->b = malloc(10);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static void foo() {\n"
+ " struct ABC *abc = g_malloc(123);\n"
+ " abc->a = abc->b = g_malloc(10);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void assign3() {
@@ -5227,6 +5756,12 @@ private:
" *f1 = f2;\n"
"}\n", "test.c");
ASSERT_EQUALS("", errout.str());
+ check("void f(struct s *f1) {\n"
+ " struct s f2;\n"
+ " f2.a = g_malloc(100);\n"
+ " *f1 = f2;\n"
+ "}\n", "test.c");
+ ASSERT_EQUALS("", errout.str());
}
void failedAllocation() {
@@ -5242,6 +5777,18 @@ private:
" return abc;\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static struct ABC * foo()\n"
+ "{\n"
+ " struct ABC *abc = g_malloc(sizeof(struct ABC));\n"
+ " abc->a = g_malloc(10);\n"
+ " if (!abc->a)\n"
+ " {\n"
+ " g_free(abc);\n"
+ " return 0;\n"
+ " }\n"
+ " return abc;\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void function1() {
@@ -5253,6 +5800,13 @@ private:
" func(abc);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static void foo()\n"
+ "{\n"
+ " struct ABC *abc = g_malloc(sizeof(struct ABC));\n"
+ " abc->a = g_malloc(10);\n"
+ " g_func(abc);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
check("static void foo()\n"
"{\n"
@@ -5261,6 +5815,13 @@ private:
" abc->a = malloc(10);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static void foo()\n"
+ "{\n"
+ " struct ABC *abc = g_malloc(sizeof(struct ABC));\n"
+ " abclist.push_back(abc);\n"
+ " abc->a = g_malloc(10);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
// #2848: Taking address in function 'assign'
@@ -5271,6 +5832,12 @@ private:
" assign(&a);\n"
"}\n", "test.c");
ASSERT_EQUALS("", errout.str());
+ check("void f() {\n"
+ " A a = { 0 };\n"
+ " a.foo = (gchar *) g_malloc(10);\n"
+ " assign(&a);\n"
+ "}\n", "test.c");
+ ASSERT_EQUALS("", errout.str());
}
// #3024: kernel list
@@ -5292,6 +5859,13 @@ private:
" a(abc.a);\n"
"}\n", "test.c");
ASSERT_EQUALS("", errout.str());
+ check("void a(char *p) { gchar *x = p; g_free(x); }\n"
+ "void b() {\n"
+ " struct ABC abc;\n"
+ " abc.a = (gchar *) g_malloc(10);\n"
+ " a(abc.a);\n"
+ "}\n", "test.c");
+ ASSERT_EQUALS("", errout.str());
}
void ifelse() {
@@ -5311,6 +5885,22 @@ private:
" free(abc);\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static void foo()\n"
+ "{\n"
+ " struct ABC *abc = g_malloc(sizeof(struct ABC));\n"
+ " if (x)"
+ " {\n"
+ " abc->a = g_malloc(10);\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " g_free(abc);\n"
+ " return;\n"
+ " }\n"
+ " g_free(abc->a);\n"
+ " g_free(abc);\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void linkedlist() {
@@ -5327,6 +5917,18 @@ private:
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("static void foo() {\n"
+ " struct ABC *abc = g_malloc(sizeof(struct ABC));\n"
+ " abc->next = g_malloc(sizeof(struct ABC));\n"
+ " abc->next->next = NULL;\n"
+ "\n"
+ " while (abc) {\n"
+ " struct ABC *next = abc->next;\n"
+ " g_free(abc);\n"
+ " abc = next;\n"
+ " }\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
void globalvar() {
@@ -5339,6 +5941,15 @@ private:
" return;\n"
"}");
ASSERT_EQUALS("", errout.str());
+ check("struct ABC *abc;\n"
+ "\n"
+ "static void foo()\n"
+ "{\n"
+ " abc = g_malloc(sizeof(struct ABC));\n"
+ " abc->a = g_malloc(10);\n"
+ " return;\n"
+ "}");
+ ASSERT_EQUALS("", errout.str());
}
// Ticket #933 Leaks with struct members not detected
@@ -5363,6 +5974,27 @@ private:
ASSERT_EQUALS("[test.c:12]: (error) Memory leak: a.f\n"
"[test.c:12]: (error) Memory leak: a.c\n"
"[test.c:12]: (error) Memory leak: a.m\n", errout.str());
+ const char code_err_glib[] = "struct A {\n"
+ " FILE* f;\n"
+ " char* c;\n"
+ " void* m;\n"
+ "};\n"
+ "\n"
+ "void func() {\n"
+ " struct A a;\n"
+ " a.f = fopen(\"test\", \"r\");\n"
+ " a.c = new char[12];\n"
+ " a.m = g_malloc(12);\n"
+ "}\n";
+
+ check(code_err_glib, "test.cpp");
+ ASSERT_EQUALS("", errout.str());
+ check(code_err_glib, "test.c");
+ TODO_ASSERT_EQUALS("[test.c:12]: (error) Memory leak: a.f\n"
+ "[test.c:12]: (error) Memory leak: a.c\n"
+ "[test.c:12]: (error) Memory leak: a.m\n",
+ "[test.c:12]: (error) Memory leak: a.f\n"
+ "[test.c:12]: (error) Memory leak: a.c\n", errout.str());
// Test OK case
const char code_ok[] = "struct A {\n"
@@ -5385,6 +6017,26 @@ private:
ASSERT_EQUALS("", errout.str());
check(code_ok, "test.c");
ASSERT_EQUALS("", errout.str());
+ const char code_ok_glib[] = "struct A {\n"
+ " FILE* f;\n"
+ " char* c;\n"
+ " void* m;\n"
+ "};\n"
+ "\n"
+ "void func() {\n"
+ " struct A a;\n"
+ " a.f = fopen(\"test\", \"r\");\n"
+ " a.c = new char[12];\n"
+ " a.m = g_malloc(12);\n"
+ " fclose(a.f);\n"
+ " delete [] a.c;\n"
+ " g_free(a.m);\n"
+ "}\n";
+
+ check(code_ok_glib, "test.cpp");
+ ASSERT_EQUALS("", errout.str());
+ check(code_ok_glib, "test.c");
+ ASSERT_EQUALS("", errout.str());
}
// don't crash
@@ -5408,6 +6060,16 @@ private:
" return;\n"
"}", /*fname=*/0, /*isCPP=*/false);
ASSERT_EQUALS("[test.c:9]: (error) Memory leak: s.state_check_buff\n", errout.str());
+ check("struct S {\n"
+ " void *state_check_buff;\n"
+ "};\n"
+ "void f() {\n"
+ " S s;\n"
+ " (s).state_check_buff = (void* )g_malloc(1);\n"
+ " if (s.state_check_buff == 0)\n"
+ " return;\n"
+ "}", /*fname=*/0, /*isCPP=*/false);
+ TODO_ASSERT_EQUALS("[test.c:9]: (error) Memory leak: s.state_check_buff\n", "", errout.str());
}
};