From df800e35d4c75caf02dfcb18695d6b46e7fbd290 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Sun, 22 Sep 2019 19:18:31 +0200 Subject: [PATCH] Fix memleak FP with return with parenthesis (#2202) * Fix memleak FP with return with parenthesis Fix FPs pointed out by daca@home on the following form: void* f(void) { void* x = malloc(1); return(x); } Fix it by only skipping tokens if there is an actual match with a variable. This allows to remove the special casing of "return;". * Add testcase with cast --- lib/checkleakautovar.cpp | 22 +++++++++++----------- test/testleakautovar.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 2314c6925..005c86961 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -930,21 +930,21 @@ void CheckLeakAutoVar::ret(const Token *tok, const VarInfo &varInfo) if (var) { bool used = false; for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { - if (tok2->str() == ";" || Token::simpleMatch(tok2, "return ;")) + if (tok2->str() == ";") break; if (!Token::Match(tok2, "return|(|{|,")) continue; - tok2 = tok2->next(); - while (tok2 && tok2->isCast() && tok2->valueType() && - (tok2->valueType()->pointer || - (tok2->valueType()->typeSize(*mSettings) == 0) || - (tok2->valueType()->typeSize(*mSettings) >= mSettings->sizeof_pointer))) - tok2 = tok2->astOperand2() ? tok2->astOperand2() : tok2->astOperand1(); - if (Token::Match(tok2, "%varid%", varid)) - tok2 = tok2->next(); - else if (Token::Match(tok2, "& %varid% . %name%", varid)) - tok2 = tok2->tokAt(4); + const Token* tok3 = tok2->next(); + while (tok3 && tok3->isCast() && tok3->valueType() && + (tok3->valueType()->pointer || + (tok3->valueType()->typeSize(*mSettings) == 0) || + (tok3->valueType()->typeSize(*mSettings) >= mSettings->sizeof_pointer))) + tok3 = tok3->astOperand2() ? tok3->astOperand2() : tok3->astOperand1(); + if (Token::Match(tok3, "%varid%", varid)) + tok2 = tok3->next(); + else if (Token::Match(tok3, "& %varid% . %name%", varid)) + tok2 = tok3->tokAt(4); else continue; if (Token::Match(tok2, "[});,]")) { diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 39d4d5276..97a0c3483 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -154,6 +154,7 @@ private: TEST_CASE(return5); TEST_CASE(return6); // #8282 return {p, p} TEST_CASE(return7); // #9343 return (uint8_t*)x + TEST_CASE(return8); // General tests: variable type, allocation type, etc TEST_CASE(test1); @@ -1758,6 +1759,32 @@ private: ASSERT_EQUALS("[test.cpp:3]: (error) Memory leak: x\n", errout.str()); } + void return8() { + check("void* f() {\n" + " void *x = malloc(1);\n" + " return (x);\n" + "}", true); + ASSERT_EQUALS("", errout.str()); + + check("void* f() {\n" + " void *x = malloc(1);\n" + " return ((x));\n" + "}", true); + ASSERT_EQUALS("", errout.str()); + + check("void* f() {\n" + " void *x = malloc(1);\n" + " return ((((x))));\n" + "}", true); + ASSERT_EQUALS("", errout.str()); + + check("char* f() {\n" + " void *x = malloc(1);\n" + " return (char*)(x);\n" + "}", true); + ASSERT_EQUALS("", errout.str()); + } + void test1() { // 3809 check("void f(double*&p) {\n" " p = malloc(0x100);\n"