Skip to content

Commit 4d01af3

Browse files
committed
Fixed false positive in CheckMemoryLeakStructMember when returning a member that has been allocated (#7302).
1 parent f6161c6 commit 4d01af3

2 files changed

Lines changed: 29 additions & 13 deletions

File tree

lib/checkmemoryleak.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2535,7 +2535,8 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable * const var
25352535
else if (tok3->str() == "return") {
25362536
// Returning from function without deallocating struct member?
25372537
if (!Token::Match(tok3, "return %varid% ;", structid) &&
2538-
!Token::Match(tok3, "return & %varid% .", structid)) {
2538+
!Token::Match(tok3, "return & %varid%", structid) &&
2539+
!(Token::Match(tok3, "return %varid% . %var%", structid) && tok3->tokAt(3)->varId() == structmemberid)) {
25392540
memoryLeak(tok3, variable->name() + "." + tok2->strAt(2), Malloc);
25402541
}
25412542
break;

test/testmemleak.cpp

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5110,14 +5110,14 @@ class TestMemleakStructMember : public TestFixture {
51105110
private:
51115111
Settings settings;
51125112

5113-
void check(const char code[], const char fname[] = 0, bool isCPP = true) {
5113+
void check(const char code[], bool isCPP = true) {
51145114
// Clear the error buffer..
51155115
errout.str("");
51165116

51175117
// Tokenize..
51185118
Tokenizer tokenizer(&settings, this);
51195119
std::istringstream istr(code);
5120-
tokenizer.tokenize(istr, fname ? fname : (isCPP ? "test.cpp" : "test.c"));
5120+
tokenizer.tokenize(istr, isCPP ? "test.cpp" : "test.c");
51215121
tokenizer.simplifyTokenList2();
51225122

51235123
// Check for memory leaks..
@@ -5245,6 +5245,21 @@ class TestMemleakStructMember : public TestFixture {
52455245
" abc->a = malloc(10);\n"
52465246
"}");
52475247
ASSERT_EQUALS("", errout.str());
5248+
5249+
// #7302
5250+
check("void* foo() {\n"
5251+
" struct ABC abc;\n"
5252+
" abc.a = malloc(10);\n"
5253+
" return abc.a;\n"
5254+
"}", false);
5255+
ASSERT_EQUALS("", errout.str());
5256+
5257+
check("void* foo() {\n"
5258+
" struct ABC abc;\n"
5259+
" abc.a = malloc(10);\n"
5260+
" return abc.b;\n"
5261+
"}", false);
5262+
ASSERT_EQUALS("[test.c:4]: (error) Memory leak: abc.a\n", errout.str());
52485263
}
52495264

52505265
void ret2() {
@@ -5429,11 +5444,11 @@ class TestMemleakStructMember : public TestFixture {
54295444
" a.m = malloc(12);\n"
54305445
"}";
54315446

5432-
check(code1, "test.cpp");
5447+
check(code1, true);
54335448
ASSERT_EQUALS("[test.cpp:12]: (error) Memory leak: a.f\n"
54345449
"[test.cpp:12]: (error) Memory leak: a.c\n"
54355450
"[test.cpp:12]: (error) Memory leak: a.m\n", errout.str());
5436-
check(code1, "test.c");
5451+
check(code1, false);
54375452
ASSERT_EQUALS("[test.c:12]: (error) Memory leak: a.f\n"
54385453
"[test.c:12]: (error) Memory leak: a.m\n", errout.str());
54395454

@@ -5454,9 +5469,9 @@ class TestMemleakStructMember : public TestFixture {
54545469
" free(a.m);\n"
54555470
"}";
54565471

5457-
check(code2, "test.cpp");
5472+
check(code2, true);
54585473
ASSERT_EQUALS("", errout.str());
5459-
check(code2, "test.c");
5474+
check(code2, false);
54605475
ASSERT_EQUALS("", errout.str());
54615476

54625477
// Test unknown struct. In C++, it might have a destructor
@@ -5465,9 +5480,9 @@ class TestMemleakStructMember : public TestFixture {
54655480
" a.f = fopen(\"test\", \"r\");\n"
54665481
"}";
54675482

5468-
check(code3, "test.cpp");
5483+
check(code3, true);
54695484
ASSERT_EQUALS("", errout.str());
5470-
check(code3, "test.c");
5485+
check(code3, false);
54715486
ASSERT_EQUALS("[test.c:4]: (error) Memory leak: a.f\n", errout.str());
54725487

54735488
// Test struct with destructor
@@ -5480,7 +5495,7 @@ class TestMemleakStructMember : public TestFixture {
54805495
" a.f = fopen(\"test\", \"r\");\n"
54815496
"}";
54825497

5483-
check(code4, "test.cpp");
5498+
check(code4, true);
54845499
ASSERT_EQUALS("", errout.str());
54855500
}
54865501

@@ -5503,7 +5518,7 @@ class TestMemleakStructMember : public TestFixture {
55035518
" (s).state_check_buff = (void* )malloc(1);\n"
55045519
" if (s.state_check_buff == 0)\n"
55055520
" return;\n"
5506-
"}", /*fname=*/0, /*isCPP=*/false);
5521+
"}", false);
55075522
ASSERT_EQUALS("[test.c:9]: (error) Memory leak: s.state_check_buff\n", errout.str());
55085523
}
55095524

@@ -5513,7 +5528,7 @@ class TestMemleakStructMember : public TestFixture {
55135528
" foo f;\n"
55145529
" ((f)->realm) = strdup(realm);\n"
55155530
" if(f->realm == NULL) {}\n"
5516-
"}", /*fname=*/0, /*isCPP=*/false);
5531+
"}", false);
55175532
ASSERT_EQUALS("[test.c:6]: (error) Memory leak: f.realm\n", errout.str());
55185533
}
55195534

@@ -5524,7 +5539,7 @@ class TestMemleakStructMember : public TestFixture {
55245539
"void func() {\n"
55255540
" struct ABC abc;\n"
55265541
" abc.a = myalloc();\n"
5527-
"}", 0, false);
5542+
"}", false);
55285543
ASSERT_EQUALS("[test.c:7]: (error) Memory leak: abc.a\n", errout.str());
55295544
}
55305545
};

0 commit comments

Comments
 (0)