Skip to content

Commit f86e83d

Browse files
committed
Memory leaks: Improved handling of allocation functions that contains ::. Ticket: danmar#4494
1 parent 444f80c commit f86e83d

2 files changed

Lines changed: 78 additions & 61 deletions

File tree

lib/checkmemoryleak.cpp

Lines changed: 67 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -140,80 +140,86 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2,
140140
if (! tok2->isName())
141141
return No;
142142

143-
// Does tok2 point on "malloc", "strdup" or "kmalloc"..
144-
static const char * const mallocfunc[] = {
145-
"malloc",
146-
"calloc",
147-
"strdup",
148-
"strndup",
149-
"kmalloc",
150-
"kzalloc",
151-
"kcalloc"
152-
};
153-
for (unsigned int i = 0; i < sizeof(mallocfunc)/sizeof(*mallocfunc); i++) {
154-
if (tok2->str() == mallocfunc[i])
143+
if (!Token::Match(tok2, "%type% :: %type%")) {
144+
// Does tok2 point on "malloc", "strdup" or "kmalloc"..
145+
static const char * const mallocfunc[] = {
146+
"malloc",
147+
"calloc",
148+
"strdup",
149+
"strndup",
150+
"kmalloc",
151+
"kzalloc",
152+
"kcalloc"
153+
};
154+
for (unsigned int i = 0; i < sizeof(mallocfunc)/sizeof(*mallocfunc); i++) {
155+
if (tok2->str() == mallocfunc[i])
156+
return Malloc;
157+
}
158+
159+
// Using realloc..
160+
if (varid && Token::Match(tok2, "realloc ( %any% ,") && tok2->tokAt(2)->varId() != varid)
155161
return Malloc;
156-
}
157162

158-
// Using realloc..
159-
if (varid && Token::Match(tok2, "realloc ( %any% ,") && tok2->tokAt(2)->varId() != varid)
160-
return Malloc;
163+
// Does tok2 point on "g_malloc", "g_strdup", ..
164+
static const char * const gmallocfunc[] = {
165+
"g_new",
166+
"g_new0",
167+
"g_try_new",
168+
"g_try_new0",
169+
"g_malloc",
170+
"g_malloc0",
171+
"g_try_malloc",
172+
"g_try_malloc0",
173+
"g_strdup",
174+
"g_strndup",
175+
"g_strdup_printf"
176+
};
177+
for (unsigned int i = 0; i < sizeof(gmallocfunc)/sizeof(*gmallocfunc); i++) {
178+
if (tok2->str() == gmallocfunc[i])
179+
return gMalloc;
180+
}
161181

162-
// Does tok2 point on "g_malloc", "g_strdup", ..
163-
static const char * const gmallocfunc[] = {
164-
"g_new",
165-
"g_new0",
166-
"g_try_new",
167-
"g_try_new0",
168-
"g_malloc",
169-
"g_malloc0",
170-
"g_try_malloc",
171-
"g_try_malloc0",
172-
"g_strdup",
173-
"g_strndup",
174-
"g_strdup_printf"
175-
};
176-
for (unsigned int i = 0; i < sizeof(gmallocfunc)/sizeof(*gmallocfunc); i++) {
177-
if (tok2->str() == gmallocfunc[i])
178-
return gMalloc;
179-
}
182+
if (Token::Match(tok2, "new struct| %type% [;()]") ||
183+
Token::Match(tok2, "new ( std :: nothrow ) struct| %type% [;()]") ||
184+
Token::Match(tok2, "new ( nothrow ) struct| %type% [;()]"))
185+
return New;
180186

181-
if (Token::Match(tok2, "new struct| %type% [;()]") ||
182-
Token::Match(tok2, "new ( std :: nothrow ) struct| %type% [;()]") ||
183-
Token::Match(tok2, "new ( nothrow ) struct| %type% [;()]"))
184-
return New;
187+
if (Token::Match(tok2, "new struct| %type% [") ||
188+
Token::Match(tok2, "new ( std :: nothrow ) struct| %type% [") ||
189+
Token::Match(tok2, "new ( nothrow ) struct| %type% ["))
190+
return NewArray;
185191

186-
if (Token::Match(tok2, "new struct| %type% [") ||
187-
Token::Match(tok2, "new ( std :: nothrow ) struct| %type% [") ||
188-
Token::Match(tok2, "new ( nothrow ) struct| %type% ["))
189-
return NewArray;
192+
if (Token::Match(tok2, "fopen|tmpfile|g_fopen ("))
193+
return File;
190194

191-
if (Token::Match(tok2, "fopen|tmpfile|g_fopen ("))
192-
return File;
195+
if (standards.posix) {
196+
if (Token::Match(tok2, "open|openat|creat|mkstemp|mkostemp (")) {
197+
// simple sanity check of function parameters..
198+
// TODO: Make such check for all these functions
199+
unsigned int num = countParameters(tok2);
200+
if (tok2->str() == "open" && num != 2 && num != 3)
201+
return No;
193202

194-
if (standards.posix) {
195-
if (Token::Match(tok2, "open|openat|creat|mkstemp|mkostemp (")) {
196-
// simple sanity check of function parameters..
197-
// TODO: Make such check for all these functions
198-
unsigned int num = countParameters(tok2);
199-
if (tok2->str() == "open" && num != 2 && num != 3)
200-
return No;
203+
// is there a user function with this name?
204+
if (tokenizer && Token::findmatch(tokenizer->tokens(), ("%type% *|&| " + tok2->str()).c_str()))
205+
return No;
206+
return Fd;
207+
}
201208

202-
// is there a user function with this name?
203-
if (tokenizer && Token::findmatch(tokenizer->tokens(), ("%type% *|&| " + tok2->str()).c_str()))
204-
return No;
205-
return Fd;
206-
}
209+
if (Token::simpleMatch(tok2, "popen ("))
210+
return Pipe;
207211

208-
if (Token::simpleMatch(tok2, "popen ("))
209-
return Pipe;
212+
if (Token::Match(tok2, "opendir|fdopendir ("))
213+
return Dir;
214+
}
210215

211-
if (Token::Match(tok2, "opendir|fdopendir ("))
212-
return Dir;
213216
}
214217

218+
while (Token::Match(tok2,"%type% :: %type%"))
219+
tok2 = tok2->tokAt(2);
220+
215221
// User function
216-
const Function* func = tokenizer->getSymbolDatabase()->findFunctionByName(tok2->str(), tok2->scope());
222+
const Function* func = tokenizer->getSymbolDatabase()->findFunctionByNameAndArgs(tok2, tok2->scope());
217223
if (func == NULL)
218224
return No;
219225

test/testmemleak.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ class TestMemleakInFunction : public TestFixture {
240240
TEST_CASE(allocfunc10);
241241
TEST_CASE(allocfunc11);
242242
TEST_CASE(allocfunc12); // #3660: allocating and returning non-local pointer => not allocfunc
243+
TEST_CASE(allocfunc13); // Ticket #4494 - class function
243244

244245
TEST_CASE(throw1);
245246
TEST_CASE(throw2);
@@ -2583,6 +2584,16 @@ class TestMemleakInFunction : public TestFixture {
25832584
ASSERT_EQUALS("", errout.str());
25842585
}
25852586

2587+
void allocfunc13() { // #4494: class function
2588+
check("namespace n {\n"
2589+
" char *a() { return malloc(100); }\n"
2590+
"}\n"
2591+
"void b() {\n"
2592+
" char *x = n::a();\n"
2593+
"}");
2594+
ASSERT_EQUALS("[test.cpp:6]: (error) Memory leak: x\n", errout.str());
2595+
}
2596+
25862597
void throw1() {
25872598
check("void foo()\n"
25882599
"{\n"

0 commit comments

Comments
 (0)