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()); } };