Fixed false positive in CheckMemoryLeakStructMember when returning a member that has been allocated (#7302).
This commit is contained in:
parent
f6161c6f89
commit
4d01af3fe1
|
@ -2535,7 +2535,8 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable * const var
|
||||||
else if (tok3->str() == "return") {
|
else if (tok3->str() == "return") {
|
||||||
// Returning from function without deallocating struct member?
|
// Returning from function without deallocating struct member?
|
||||||
if (!Token::Match(tok3, "return %varid% ;", structid) &&
|
if (!Token::Match(tok3, "return %varid% ;", structid) &&
|
||||||
!Token::Match(tok3, "return & %varid% .", structid)) {
|
!Token::Match(tok3, "return & %varid%", structid) &&
|
||||||
|
!(Token::Match(tok3, "return %varid% . %var%", structid) && tok3->tokAt(3)->varId() == structmemberid)) {
|
||||||
memoryLeak(tok3, variable->name() + "." + tok2->strAt(2), Malloc);
|
memoryLeak(tok3, variable->name() + "." + tok2->strAt(2), Malloc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -5110,14 +5110,14 @@ public:
|
||||||
private:
|
private:
|
||||||
Settings settings;
|
Settings settings;
|
||||||
|
|
||||||
void check(const char code[], const char fname[] = 0, bool isCPP = true) {
|
void check(const char code[], bool isCPP = true) {
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize(istr, fname ? fname : (isCPP ? "test.cpp" : "test.c"));
|
tokenizer.tokenize(istr, isCPP ? "test.cpp" : "test.c");
|
||||||
tokenizer.simplifyTokenList2();
|
tokenizer.simplifyTokenList2();
|
||||||
|
|
||||||
// Check for memory leaks..
|
// Check for memory leaks..
|
||||||
|
@ -5245,6 +5245,21 @@ private:
|
||||||
" abc->a = malloc(10);\n"
|
" abc->a = malloc(10);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// #7302
|
||||||
|
check("void* foo() {\n"
|
||||||
|
" struct ABC abc;\n"
|
||||||
|
" abc.a = malloc(10);\n"
|
||||||
|
" return abc.a;\n"
|
||||||
|
"}", false);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void* foo() {\n"
|
||||||
|
" struct ABC abc;\n"
|
||||||
|
" abc.a = malloc(10);\n"
|
||||||
|
" return abc.b;\n"
|
||||||
|
"}", false);
|
||||||
|
ASSERT_EQUALS("[test.c:4]: (error) Memory leak: abc.a\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ret2() {
|
void ret2() {
|
||||||
|
@ -5429,11 +5444,11 @@ private:
|
||||||
" a.m = malloc(12);\n"
|
" a.m = malloc(12);\n"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
check(code1, "test.cpp");
|
check(code1, true);
|
||||||
ASSERT_EQUALS("[test.cpp:12]: (error) Memory leak: a.f\n"
|
ASSERT_EQUALS("[test.cpp:12]: (error) Memory leak: a.f\n"
|
||||||
"[test.cpp:12]: (error) Memory leak: a.c\n"
|
"[test.cpp:12]: (error) Memory leak: a.c\n"
|
||||||
"[test.cpp:12]: (error) Memory leak: a.m\n", errout.str());
|
"[test.cpp:12]: (error) Memory leak: a.m\n", errout.str());
|
||||||
check(code1, "test.c");
|
check(code1, false);
|
||||||
ASSERT_EQUALS("[test.c:12]: (error) Memory leak: a.f\n"
|
ASSERT_EQUALS("[test.c:12]: (error) Memory leak: a.f\n"
|
||||||
"[test.c:12]: (error) Memory leak: a.m\n", errout.str());
|
"[test.c:12]: (error) Memory leak: a.m\n", errout.str());
|
||||||
|
|
||||||
|
@ -5454,9 +5469,9 @@ private:
|
||||||
" free(a.m);\n"
|
" free(a.m);\n"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
check(code2, "test.cpp");
|
check(code2, true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
check(code2, "test.c");
|
check(code2, false);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
// Test unknown struct. In C++, it might have a destructor
|
// Test unknown struct. In C++, it might have a destructor
|
||||||
|
@ -5465,9 +5480,9 @@ private:
|
||||||
" a.f = fopen(\"test\", \"r\");\n"
|
" a.f = fopen(\"test\", \"r\");\n"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
check(code3, "test.cpp");
|
check(code3, true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
check(code3, "test.c");
|
check(code3, false);
|
||||||
ASSERT_EQUALS("[test.c:4]: (error) Memory leak: a.f\n", errout.str());
|
ASSERT_EQUALS("[test.c:4]: (error) Memory leak: a.f\n", errout.str());
|
||||||
|
|
||||||
// Test struct with destructor
|
// Test struct with destructor
|
||||||
|
@ -5480,7 +5495,7 @@ private:
|
||||||
" a.f = fopen(\"test\", \"r\");\n"
|
" a.f = fopen(\"test\", \"r\");\n"
|
||||||
"}";
|
"}";
|
||||||
|
|
||||||
check(code4, "test.cpp");
|
check(code4, true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5503,7 +5518,7 @@ private:
|
||||||
" (s).state_check_buff = (void* )malloc(1);\n"
|
" (s).state_check_buff = (void* )malloc(1);\n"
|
||||||
" if (s.state_check_buff == 0)\n"
|
" if (s.state_check_buff == 0)\n"
|
||||||
" return;\n"
|
" return;\n"
|
||||||
"}", /*fname=*/0, /*isCPP=*/false);
|
"}", false);
|
||||||
ASSERT_EQUALS("[test.c:9]: (error) Memory leak: s.state_check_buff\n", errout.str());
|
ASSERT_EQUALS("[test.c:9]: (error) Memory leak: s.state_check_buff\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5513,7 +5528,7 @@ private:
|
||||||
" foo f;\n"
|
" foo f;\n"
|
||||||
" ((f)->realm) = strdup(realm);\n"
|
" ((f)->realm) = strdup(realm);\n"
|
||||||
" if(f->realm == NULL) {}\n"
|
" if(f->realm == NULL) {}\n"
|
||||||
"}", /*fname=*/0, /*isCPP=*/false);
|
"}", false);
|
||||||
ASSERT_EQUALS("[test.c:6]: (error) Memory leak: f.realm\n", errout.str());
|
ASSERT_EQUALS("[test.c:6]: (error) Memory leak: f.realm\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5524,7 +5539,7 @@ private:
|
||||||
"void func() {\n"
|
"void func() {\n"
|
||||||
" struct ABC abc;\n"
|
" struct ABC abc;\n"
|
||||||
" abc.a = myalloc();\n"
|
" abc.a = myalloc();\n"
|
||||||
"}", 0, false);
|
"}", false);
|
||||||
ASSERT_EQUALS("[test.c:7]: (error) Memory leak: abc.a\n", errout.str());
|
ASSERT_EQUALS("[test.c:7]: (error) Memory leak: abc.a\n", errout.str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue