diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index b2f97693cd6..816c0347c85 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -1022,10 +1022,8 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope) const Token* tok2 = tok->next()->astParent(); while (tok2 && (tok2->isCast() || Token::Match(tok2, "?|:"))) tok2 = tok2->astParent(); - if (Token::Match(tok2, "%assign%")) // TODO: check if function returns allocated resource - continue; - if (Token::simpleMatch(tok->astTop(), "return")) - continue; + const bool hasAssign = Token::Match(tok2, "%assign%"); + const bool hasReturn = Token::simpleMatch(tok->astTop(), "return"); const std::string& functionName = tok->str(); if ((tok->isCpp() && functionName == "delete") || @@ -1037,6 +1035,12 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope) if (!tok->isKeyword() && !tok->function() && !mSettings->library.isLeakIgnore(functionName)) continue; + if ((hasAssign || hasReturn) && !tok->function()) { + const std::string& ret = mSettings->library.returnValueType(tok); + if (ret.empty() || endsWith(ret, "*")) + continue; + } + const std::vector args = getArguments(tok); int argnr = -1; for (const Token* arg : args) { diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 1ed88120886..d7198b37868 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -2603,6 +2603,17 @@ class TestMemleakNoVar : public TestFixture { " a.g(new int);\n" "}\n"); ASSERT_EQUALS("", errout_str()); + + check("int f() {\n" // #11184 + " return strlen(new char[4]{});\n" + "}\n" + "int g() {\n" + " int i = strlen(new char[4]{});\n" + " return i;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:19]: (error) Allocation with new, strlen doesn't release it. [leakNoVarFunctionCall]\n" + "[test.cpp:5:20]: (error) Allocation with new, strlen doesn't release it. [leakNoVarFunctionCall]\n", + errout_str()); } void missingAssignment() {