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 9420d7d75..e3370fd89 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);
@@ -937,6 +941,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());
}
@@ -1020,6 +1042,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() {
@@ -1123,6 +1153,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() {
@@ -1157,6 +1197,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() {
@@ -1502,6 +1557,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());
}
@@ -1666,6 +1729,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() {
@@ -1679,6 +1754,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() {
@@ -1751,6 +1836,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() {
@@ -1765,6 +1872,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() {
@@ -2387,6 +2504,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() {
@@ -2498,6 +2625,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"
@@ -2536,6 +2677,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());
}
@@ -2719,6 +2876,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());
}
@@ -2897,6 +3073,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"
@@ -2906,6 +3090,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"
@@ -2915,6 +3107,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"
@@ -2924,6 +3124,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"
@@ -2933,6 +3141,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"
@@ -2966,6 +3182,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() {
@@ -2975,6 +3201,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());
}
@@ -3013,6 +3245,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"
@@ -3022,6 +3261,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"
@@ -3032,6 +3279,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"
@@ -3040,6 +3295,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"
@@ -3048,6 +3310,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"
@@ -3055,6 +3324,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"
@@ -3062,6 +3337,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() {
@@ -3071,6 +3352,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() {
@@ -3099,6 +3385,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() {
@@ -3120,6 +3413,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() {
@@ -3129,6 +3430,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() {
@@ -3141,6 +3448,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());
}
@@ -3162,6 +3478,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());
}
@@ -3227,6 +3549,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());
}
@@ -3737,6 +4073,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() {
@@ -4048,6 +4397,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"
@@ -4064,6 +4432,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() {
@@ -4531,6 +4914,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"
@@ -4541,6 +4934,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() {
@@ -5008,6 +5410,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"
@@ -5020,6 +5433,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() {
@@ -5034,6 +5458,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());
}
};
@@ -5118,6 +5553,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"
@@ -5125,6 +5567,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"
@@ -5138,6 +5586,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"
@@ -5150,6 +5610,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_() {
@@ -5166,6 +5637,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() {
@@ -5176,12 +5660,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() {
@@ -5192,6 +5688,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() {
@@ -5201,6 +5704,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"
@@ -5209,6 +5718,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"
@@ -5219,6 +5735,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());
}
@@ -5228,6 +5752,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() {
@@ -5237,6 +5766,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() {
@@ -5252,6 +5787,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() {
@@ -5263,6 +5810,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"
@@ -5271,6 +5825,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'
@@ -5281,6 +5842,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
@@ -5302,6 +5869,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() {
@@ -5321,6 +5895,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() {
@@ -5337,6 +5927,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() {
@@ -5349,6 +5951,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
@@ -5373,6 +5984,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"
@@ -5395,6 +6027,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
@@ -5418,6 +6070,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());
}
};