From 4996ec190ecf27a4bf018eb0dcd12e2a51fd550e Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Tue, 7 Jul 2020 23:46:24 +0200 Subject: [PATCH] Fix #9652 (fp memleak with function call with cast) When the first argument was (void *)(1), at the start of the second iteration, arg was pointing to the "1", which caused problems for nextArgument(), which saw the ")" as the next token and returned nullptr, signalling that there are no more arguments. Instead, save the first token in the argument, which makes nextArgument() do the right thing. --- lib/checkleakautovar.cpp | 3 ++- test/testleakautovar.cpp | 43 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 7400f39b4..551e475ce 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -856,7 +856,8 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin } int argNr = 1; - for (const Token *arg = tokFirstArg; arg; arg = arg->nextArgument()) { + for (const Token *funcArg = tokFirstArg; funcArg; funcArg = funcArg->nextArgument()) { + const Token* arg = funcArg; if (mTokenizer->isCPP() && arg->str() == "new") { arg = arg->next(); if (Token::simpleMatch(arg, "( std :: nothrow )")) diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 28a6fa532..7aea76b06 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -184,6 +184,8 @@ private: TEST_CASE(smartPtrInContainer); // #8262 TEST_CASE(recursiveCountLimit); // #5872 #6157 #9097 + + TEST_CASE(functionCallCastConfig); // #9652 } void check(const char code[], bool cpp = false) { @@ -202,6 +204,22 @@ private: c.runChecks(&tokenizer, &settings, this); } + void check(const char code[], Settings & settings) { + // Clear the error buffer.. + errout.str(""); + + // Tokenize.. + Tokenizer tokenizer(&settings, this); + std::istringstream istr(code); + tokenizer.tokenize(istr, "test.cpp"); + + // Check for leaks.. + CheckLeakAutoVar c; + settings.checkLibrary = true; + settings.addEnabled("information"); + c.runChecks(&tokenizer, &settings, this); + } + void checkP(const char code[], bool cpp = false) { // Clear the error buffer.. errout.str(""); @@ -2023,6 +2041,31 @@ private: "}")); } + void functionCallCastConfig() { // #9652 + Settings settingsFunctionCall = settings; + + const char xmldata[] = "\n" + "\n" + " \n" + " false\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + tinyxml2::XMLDocument doc; + doc.Parse(xmldata, sizeof(xmldata)); + settingsFunctionCall.library.load(doc); + check("void test_func()\n" + "{\n" + " char * buf = malloc(4);\n" + " free_func((void *)(1), buf);\n" + "}", settingsFunctionCall); + ASSERT_EQUALS("[test.cpp:5]: (information) --check-library: Function free_func() should have / configuration\n", errout.str()); + } }; REGISTER_TEST(TestLeakAutoVar)