diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index a61ac12c3..240dd82f6 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -793,8 +793,13 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable * const var auto isMemberAssignment = [](const Token* varTok, int varId) -> std::pair { if (varTok->varId() != varId) return {}; - const Token* top = varTok->astTop(); - if (!Token::simpleMatch(top, "=")) + const Token* top = varTok; + while (top->astParent()) { + if (top->astParent()->str() == "(") + return {}; + top = top->astParent(); + } + if (!Token::simpleMatch(top, "=") || !precedes(varTok, top)) return {}; const Token* dot = top->astOperand1(); while (dot && dot->str() != ".") @@ -824,7 +829,7 @@ void CheckMemoryLeakStructMember::checkStructVariable(const Variable * const var break; // Struct member is allocated => check if it is also properly deallocated.. - else if ((assignToks = isMemberAssignment(tok2, variable->declarationId())).first) { + else if ((assignToks = isMemberAssignment(tok2, variable->declarationId())).first && assignToks.first->varId()) { if (getAllocationType(assignToks.second, assignToks.first->varId()) == AllocType::No) continue; diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index fa77369a1..b5ea3cb6d 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -1909,6 +1909,19 @@ private: ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: s.p\n" "[test.cpp:5]: (error) Memory leak: s.q\n", errout.str()); + + check("struct S** f(struct S** s) {\n" // don't throw + " struct S** ret = malloc(sizeof(*ret));\n" + " ret[0] = malloc(sizeof(**s));\n" + " ret[0]->g = strdup(s[0]->g);\n" + " return ret;\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + + check("void run_rcmd(enum rcommand rcmd, rsh_session *sess, char *cmd) {\n" + " sess->fp = popen(cmd, rcmd == RSH_PIPE_READ ? \"r\" : \"w\");\n" + "}\n", false); + ASSERT_EQUALS("", errout.str()); } void failedAllocation() {