diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 6fb696000..a756e0693 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -985,31 +985,40 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope) // parse the executable scope until tok is reached... for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { // allocating memory in parameter for function call.. - if (!(Token::Match(tok, "[(,] %name% (") && Token::Match(tok->linkAt(2), ") [,)]"))) + if (!Token::Match(tok, "%name% (")) continue; - if (getAllocationType(tok->next(), 0) == No) + + // check if the output of the function is assigned + const Token* tok2 = tok->next()->astParent(); + while (tok2 && tok2->isCast()) + tok2 = tok2->astParent(); + if (tok2 && tok2->isAssignmentOp()) continue; - // locate outer function call.. - const Token* tok3 = tok; - while (tok3 && tok3->astParent() && tok3->str() == ",") - tok3 = tok3->astParent(); - if (!tok3 || tok3->str() != "(") - continue; - // Is it a function call.. - if (!Token::Match(tok3->tokAt(-2), "!!= %name% (")) - continue; - const std::string& functionName = tok3->strAt(-1); + + const std::string& functionName = tok->str(); if ((mTokenizer->isCPP() && functionName == "delete") || functionName == "free" || functionName == "fclose" || functionName == "realloc") break; - if (isReopenStandardStream(tok->next())) + + if (!CheckMemoryLeakInFunction::test_white_list(functionName, mSettings, mTokenizer->isCPP())) continue; - if (CheckMemoryLeakInFunction::test_white_list(functionName, mSettings, mTokenizer->isCPP())) { - functionCallLeak(tok, tok->strAt(1), functionName); + + const std::vector args = getArguments(tok); + for (const Token* arg : args) { + if (arg->isOp()) + continue; + while (arg->astOperand1()) + arg = arg->astOperand1(); + if (getAllocationType(arg, 0) == No) + continue; + if (isReopenStandardStream(arg)) + continue; + functionCallLeak(arg, arg->str(), functionName); break; } + } } diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 4932bfc3d..c4554d28e 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -2058,7 +2058,6 @@ private: Tokenizer tokenizer(&settings, this); std::istringstream istr(code); tokenizer.tokenize(istr, "test.cpp"); - tokenizer.simplifyTokenList2(); // Check for memory leaks.. CheckMemoryLeakNoVar checkMemoryLeakNoVar(&tokenizer, &settings, this); @@ -2144,6 +2143,22 @@ private: " assert(freopen(\"/dev/null\", \"r\", stdin));\n" "}"); ASSERT_EQUALS("", errout.str()); + + check("void x() {\n" + " strcpy(a, (void*)strdup(p));\n" + "}"); + ASSERT_EQUALS("[test.cpp:2]: (error) Allocation with strdup, strcpy doesn't release it.\n", errout.str()); + + check("void* malloc1() {\n" + " return (malloc(1));\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + check("char *x() {\n" + " char *ret = (char*)strcpy(malloc(10), \"abc\");\n" + " return ret;\n" + "}"); + ASSERT_EQUALS("", errout.str()); } void missingAssignment() {