diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index c12011c92..264502acf 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -930,13 +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() == ";") + if (tok2->str() == ";" || Token::simpleMatch(tok2, "return ;")) break; - if (Token::Match(tok2, "return|(|{|, %varid% [});,]", varid)) { - used = true; - break; - } - if (Token::Match(tok2, "return|(|{|, & %varid% . %name% [});,]", varid)) { + if (!Token::Match(tok2, "return|(|{|,")) + continue; + + tok2 = tok2->next(); + while (tok2 && tok2->isCast() && (tok2->valueType()->pointer || (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); + else + continue; + if (Token::Match(tok2, "[});,]")) { used = true; break; } diff --git a/test/testleakautovar.cpp b/test/testleakautovar.cpp index 878e71c77..d0d738715 100644 --- a/test/testleakautovar.cpp +++ b/test/testleakautovar.cpp @@ -144,6 +144,7 @@ private: TEST_CASE(return4); TEST_CASE(return5); TEST_CASE(return6); // #8282 return {p, p} + TEST_CASE(return7); // #9343 return (uint8_t*)x // General tests: variable type, allocation type, etc TEST_CASE(test1); @@ -521,6 +522,16 @@ private: " return p;\n" "}", true); ASSERT_EQUALS("", errout.str()); + + check("void f(void* p) {\n" + " if (a) {\n" + " free(p);\n" + " return;\n" + " }\n" + " g(p);\n" + " return;\n" + "}"); + ASSERT_EQUALS("", errout.str()); } void deallocuse5() { // #4018 @@ -1694,6 +1705,38 @@ private: ASSERT_EQUALS("", errout.str()); } + void return7() { // #9343 + check("uint8_t *f() {\n" + " void *x = malloc(1);\n" + " return (uint8_t *)x;\n" + "}", true); + ASSERT_EQUALS("", errout.str()); + + check("uint8_t f() {\n" + " void *x = malloc(1);\n" + " return (uint8_t)x;\n" + "}", true); + ASSERT_EQUALS("[test.cpp:3]: (error) Memory leak: x\n", errout.str()); + + check("void** f() {\n" + " void *x = malloc(1);\n" + " return (void**)x;\n" + "}", true); + ASSERT_EQUALS("", errout.str()); + + check("void* f() {\n" + " void *x = malloc(1);\n" + " return (long long)x;\n" + "}", true); + ASSERT_EQUALS("", errout.str()); + + check("void* f() {\n" + " void *x = malloc(1);\n" + " return (void*)(short)x;\n" + "}", true); + ASSERT_EQUALS("[test.cpp:3]: (error) Memory leak: x\n", errout.str()); + } + void test1() { // 3809 check("void f(double*&p) {\n" " p = malloc(0x100);\n"