Fixed #933 (Leaks with struct members not detected)
This commit is contained in:
parent
2bc67d72c2
commit
548dd42aaf
|
@ -2589,7 +2589,9 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable * const var
|
|||
break;
|
||||
|
||||
// Struct member is allocated => check if it is also properly deallocated..
|
||||
else if (Token::Match(tok2->previous(), "[;{}] %varid% . %var% = malloc|strdup|kmalloc (", variable->varId())) {
|
||||
else if (Token::Match(tok2->previous(), "[;{}] %varid% . %var% = malloc|strdup|kmalloc (", variable->varId())
|
||||
|| Token::Match(tok2->previous(), "[;{}] %varid% . %var% = new ", variable->varId())
|
||||
|| Token::Match(tok2->previous(), "[;{}] %varid% . %var% = fopen (", variable->varId())) {
|
||||
const unsigned int structid(variable->varId());
|
||||
const unsigned int structmemberid(tok2->tokAt(2)->varId());
|
||||
|
||||
|
@ -2608,7 +2610,10 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable * const var
|
|||
}
|
||||
|
||||
// Deallocating the struct member..
|
||||
else if (Token::Match(tok3, "free|kfree ( %var% . %varid% )", structmemberid)) {
|
||||
else if (Token::Match(tok3, "free|kfree ( %var% . %varid% )", structmemberid)
|
||||
|| Token::Match(tok3, "delete %var% . %varid%", structmemberid)
|
||||
|| Token::Match(tok3, "delete [ ] %var% . %varid%", structmemberid)
|
||||
|| Token::Match(tok3, "fclose ( %var% . %varid%", structmemberid)) {
|
||||
// If the deallocation happens at the base level, don't check this member anymore
|
||||
if (indentlevel3 == 0)
|
||||
break;
|
||||
|
|
|
@ -5079,7 +5079,7 @@ private:
|
|||
TEST_CASE(globalvar);
|
||||
|
||||
// local struct variable
|
||||
TEST_CASE(localvar);
|
||||
TEST_CASE(localvars);
|
||||
}
|
||||
|
||||
void err() {
|
||||
|
@ -5323,16 +5323,50 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void localvar() {
|
||||
const char code[] = "void foo() {\n"
|
||||
" struct ABC abc;\n"
|
||||
" abc.a = malloc(10);\n"
|
||||
"}\n";
|
||||
// Ticket #933 Leaks with struct members not detected
|
||||
void localvars() {
|
||||
// Test error case
|
||||
const char code_err[] = "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 = malloc(12);\n"
|
||||
"}\n";
|
||||
|
||||
check(code, "test.cpp");
|
||||
check(code_err, "test.cpp");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
check(code_err, "test.c");
|
||||
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());
|
||||
|
||||
// Test OK case
|
||||
const char code_ok[] = "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 = malloc(12);\n"
|
||||
" fclose(a.f);\n"
|
||||
" delete [] a.c;\n"
|
||||
" free(a.m);\n"
|
||||
"}\n";
|
||||
|
||||
check(code_ok, "test.cpp");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
check(code_ok, "test.c");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
check(code, "test.c");
|
||||
ASSERT_EQUALS("[test.c:4]: (error) Memory leak: abc.a\n", errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue