Skip to content

Commit 363a596

Browse files
authored
fix #13098: False negative: memory leak not found when deallocation is conditional (regression) (danmar#6989)
1 parent bdfaff6 commit 363a596

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

lib/checkleakautovar.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,16 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
450450

451451
// if/else
452452
else if (Token::simpleMatch(tok, "if (")) {
453+
454+
bool skipIfBlock = false;
455+
bool skipElseBlock = false;
456+
const Token *condTok = tok->astSibling();
457+
458+
if (condTok->hasKnownIntValue()) {
459+
skipIfBlock = !condTok->getKnownIntValue();
460+
skipElseBlock = !skipIfBlock;
461+
}
462+
453463
// Parse function calls inside the condition
454464

455465
const Token * closingParenthesis = tok->linkAt(1);
@@ -565,13 +575,13 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
565575
return ChildrenToVisit::none;
566576
});
567577

568-
if (!checkScope(closingParenthesis->next(), varInfo1, notzero, recursiveCount)) {
578+
if (!skipIfBlock && !checkScope(closingParenthesis->next(), varInfo1, notzero, recursiveCount)) {
569579
varInfo.clear();
570580
continue;
571581
}
572582
closingParenthesis = closingParenthesis->linkAt(1);
573583
if (Token::simpleMatch(closingParenthesis, "} else {")) {
574-
if (!checkScope(closingParenthesis->tokAt(2), varInfo2, notzero, recursiveCount)) {
584+
if (!skipElseBlock && !checkScope(closingParenthesis->tokAt(2), varInfo2, notzero, recursiveCount)) {
575585
varInfo.clear();
576586
return false;
577587
}

test/testleakautovar.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ class TestLeakAutoVar : public TestFixture {
176176
TEST_CASE(return8);
177177
TEST_CASE(return9);
178178
TEST_CASE(return10);
179+
TEST_CASE(return11); // #13098
179180

180181
// General tests: variable type, allocation type, etc
181182
TEST_CASE(test1);
@@ -1686,7 +1687,7 @@ class TestLeakAutoVar : public TestFixture {
16861687
" free(p);\n"
16871688
" if (q == NULL)\n"
16881689
" return;\n"
1689-
" free(q)\n"
1690+
" free(q);\n"
16901691
"}");
16911692
ASSERT_EQUALS("[test.c:3] -> [test.c:8]: (error) Memory pointed to by 'p' is freed twice.\n", errout_str());
16921693
}
@@ -2745,6 +2746,18 @@ class TestLeakAutoVar : public TestFixture {
27452746
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Returning/dereferencing 'p' after it is deallocated / released\n", errout_str());
27462747
}
27472748

2749+
void return11() { // #13098
2750+
check("char malloc_memleak(void) {\n"
2751+
" bool flag = false;\n"
2752+
" char *ptr = malloc(10);\n"
2753+
" if (flag) {\n"
2754+
" free(ptr);\n"
2755+
" }\n"
2756+
" return 'a';\n"
2757+
"}\n", true);
2758+
ASSERT_EQUALS("[test.cpp:7]: (error) Memory leak: ptr\n", errout_str());
2759+
}
2760+
27482761
void test1() {
27492762
check("void f(double*&p) {\n" // 3809
27502763
" p = malloc(0x100);\n"

0 commit comments

Comments
 (0)