diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 8d38c7fbb..3db1318ed 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -2535,7 +2535,8 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable * const var else if (tok3->str() == "return") { // Returning from function without deallocating struct member? 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); } break; diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 289d6bd3a..1eff8b613 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -5110,14 +5110,14 @@ public: private: 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.. errout.str(""); // Tokenize.. Tokenizer tokenizer(&settings, this); std::istringstream istr(code); - tokenizer.tokenize(istr, fname ? fname : (isCPP ? "test.cpp" : "test.c")); + tokenizer.tokenize(istr, isCPP ? "test.cpp" : "test.c"); tokenizer.simplifyTokenList2(); // Check for memory leaks.. @@ -5245,6 +5245,21 @@ private: " abc->a = malloc(10);\n" "}"); 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() { @@ -5429,11 +5444,11 @@ private: " a.m = malloc(12);\n" "}"; - check(code1, "test.cpp"); + check(code1, true); 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.m\n", errout.str()); - check(code1, "test.c"); + check(code1, false); ASSERT_EQUALS("[test.c:12]: (error) Memory leak: a.f\n" "[test.c:12]: (error) Memory leak: a.m\n", errout.str()); @@ -5454,9 +5469,9 @@ private: " free(a.m);\n" "}"; - check(code2, "test.cpp"); + check(code2, true); ASSERT_EQUALS("", errout.str()); - check(code2, "test.c"); + check(code2, false); ASSERT_EQUALS("", errout.str()); // Test unknown struct. In C++, it might have a destructor @@ -5465,9 +5480,9 @@ private: " a.f = fopen(\"test\", \"r\");\n" "}"; - check(code3, "test.cpp"); + check(code3, true); ASSERT_EQUALS("", errout.str()); - check(code3, "test.c"); + check(code3, false); ASSERT_EQUALS("[test.c:4]: (error) Memory leak: a.f\n", errout.str()); // Test struct with destructor @@ -5480,7 +5495,7 @@ private: " a.f = fopen(\"test\", \"r\");\n" "}"; - check(code4, "test.cpp"); + check(code4, true); ASSERT_EQUALS("", errout.str()); } @@ -5503,7 +5518,7 @@ private: " (s).state_check_buff = (void* )malloc(1);\n" " if (s.state_check_buff == 0)\n" " return;\n" - "}", /*fname=*/0, /*isCPP=*/false); + "}", false); ASSERT_EQUALS("[test.c:9]: (error) Memory leak: s.state_check_buff\n", errout.str()); } @@ -5513,7 +5528,7 @@ private: " foo f;\n" " ((f)->realm) = strdup(realm);\n" " if(f->realm == NULL) {}\n" - "}", /*fname=*/0, /*isCPP=*/false); + "}", false); ASSERT_EQUALS("[test.c:6]: (error) Memory leak: f.realm\n", errout.str()); } @@ -5524,7 +5539,7 @@ private: "void func() {\n" " struct ABC abc;\n" " abc.a = myalloc();\n" - "}", 0, false); + "}", false); ASSERT_EQUALS("[test.c:7]: (error) Memory leak: abc.a\n", errout.str()); } };