diff --git a/src/checkmemoryleak.cpp b/src/checkmemoryleak.cpp index fb7601146..7b962f917 100644 --- a/src/checkmemoryleak.cpp +++ b/src/checkmemoryleak.cpp @@ -25,6 +25,7 @@ #include #include #include +#include //--------------------------------------------------------------------------- @@ -1923,6 +1924,13 @@ void CheckMemoryLeakInClass::variable(const char classname[], const Token *tokVa void CheckMemoryLeakStructMember::check() { + // This should be in the CheckMemoryLeak base class + std::set ignoredFunctions; + ignoredFunctions.insert("if"); + ignoredFunctions.insert("for"); + ignoredFunctions.insert("while"); + ignoredFunctions.insert("malloc"); + for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { // Locate struct variables.. @@ -2069,6 +2077,40 @@ void CheckMemoryLeakStructMember::check() // goto isn't handled well.. bail out even though there might be leaks else if (tok3->str() == "goto") break; + + // using struct in a function call.. + else if (Token::Match(tok3, "%var% (")) + { + // Calling non-function / function that doesn't deallocate? + if (ignoredFunctions.find(tok3->str()) != ignoredFunctions.end()) + continue; + + // Check if the struct is used.. + bool deallocated = false; + unsigned int parlevel = 0; + for (const Token *tok4 = tok3; tok4; tok4 = tok4->next()) + { + if (tok4->str() == "(") + ++parlevel; + + else if (tok4->str() == ")") + { + if (parlevel <= 1) + break; + --parlevel; + } + + if (Token::Match(tok4, "[(,] %varid% [,)]", structid)) + { + /** @todo check if the function deallocates the memory */ + deallocated = true; + break; + } + } + + if (deallocated) + break; + } } } } diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index d3e5664e2..f8f0f9299 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -2806,6 +2806,9 @@ private: // Failed allocation TEST_CASE(failedAllocation); + + // Deallocating in a function + TEST_CASE(function); } void err() @@ -2929,6 +2932,18 @@ private: "}\n"); ASSERT_EQUALS("", errout.str()); } + + void function() + { + // Not found function => assume that the function may deallocate + check("static void foo()\n" + "{\n" + " struct ABC *abc = malloc(sizeof(struct ABC));\n" + " abc->a = malloc(10);\n" + " func(abc);\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + } };