diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 024c2b5822d..355b0d809d7 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -858,8 +858,14 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable* const vari // This struct member is allocated.. check that it is deallocated int indentlevel3 = indentlevel2; for (const Token *tok3 = tok2; tok3; tok3 = tok3->next()) { - if (tok3->str() == "{") + if (tok3->str() == "{") { + if (tok3->scope()->type == ScopeType::eIf && tok3 == tok3->scope()->bodyStart) { // bailout: member checked in if condition + const Token* const condBeg = tok3->scope()->classDef->tokAt(1); + if (Token::findmatch(condBeg, ". %varid%", condBeg->link(), assignToks.first->varId())) + break; + } ++indentlevel3; + } else if (tok3->str() == "}") { if (indentlevel3 == 0) { diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 6e4e6cdf875..b9a8a4e63df 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -1941,6 +1941,18 @@ class TestMemleakStructMember : public TestFixture { "[test.cpp:10:5]: (error) Resource leak: s.fd [resourceLeak]\n" "[test.cpp:16:1]: (error) Resource leak: s.fd [resourceLeak]\n", errout_str()); + + check("struct S { int fd; };\n" // #13031 + "void f() {\n" + " struct S* s = malloc(sizeof(struct S));\n" + " s->fd = open(\"abc\", O_RDWR | O_NOCTTY);\n" + " if (s->fd < 0) {\n" + " free(s);\n" + " return NULL;\n" + " }\n" + " return s;\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void failedAllocation() {