Fixed #933 (Leaks with struct members not detected)

This commit is contained in:
Baris Demiray 2013-04-26 16:11:57 +02:00 committed by Daniel Marjamäki
parent 2bc67d72c2
commit 548dd42aaf
2 changed files with 50 additions and 11 deletions

View File

@ -2589,7 +2589,9 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable * const var
break; break;
// Struct member is allocated => check if it is also properly deallocated.. // 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 structid(variable->varId());
const unsigned int structmemberid(tok2->tokAt(2)->varId()); const unsigned int structmemberid(tok2->tokAt(2)->varId());
@ -2608,7 +2610,10 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable * const var
} }
// Deallocating the struct member.. // 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 the deallocation happens at the base level, don't check this member anymore
if (indentlevel3 == 0) if (indentlevel3 == 0)
break; break;

View File

@ -5079,7 +5079,7 @@ private:
TEST_CASE(globalvar); TEST_CASE(globalvar);
// local struct variable // local struct variable
TEST_CASE(localvar); TEST_CASE(localvars);
} }
void err() { void err() {
@ -5323,16 +5323,50 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void localvar() { // Ticket #933 Leaks with struct members not detected
const char code[] = "void foo() {\n" void localvars() {
" struct ABC abc;\n" // Test error case
" abc.a = malloc(10);\n" 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"; "}\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()); ASSERT_EQUALS("", errout.str());
check(code, "test.c");
ASSERT_EQUALS("[test.c:4]: (error) Memory leak: abc.a\n", errout.str());
} }
}; };