From 09d0cc46b6a0642b02a46f0ac59bc14a914adabb Mon Sep 17 00:00:00 2001 From: Aaron Danen Date: Wed, 29 Jul 2026 12:11:43 -0700 Subject: [PATCH 1/4] Fix #14949: FP when passing resource to ctor --- lib/checkmemoryleak.cpp | 5 +++-- test/testmemleak.cpp | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index cc8b6853f11..2af137ccce9 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -517,7 +517,7 @@ void CheckMemoryLeakInClassImpl::check() // only check classes and structures for (const Scope * scope : symbolDatabase->classAndStructScopes) { for (const Variable &var : scope->varlist) { - if (!var.isStatic() && (var.isPointer() || var.isPointerArray())) { + if (!var.isStatic()) { // allocation but no deallocation of private variables in public function.. const Token *tok = var.typeStartToken(); // Either it is of standard type or a non-derived type @@ -1046,7 +1046,8 @@ void CheckMemoryLeakNoVarImpl::checkForUnreleasedInputArgument(const Scope *scop const AllocType alloc = getAllocationType(arg, 0); if (alloc == No) continue; - if (alloc == New || alloc == NewArray) { + //if (alloc == New || alloc == NewArray) { + else { const Token* typeTok = arg->next(); bool bail = !typeTok->isStandardType() && (!typeTok->valueType() || diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index 783a10ad089..cd6249ab3d3 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -2628,6 +2628,23 @@ class TestMemleakNoVar : public TestFixture { "[test.cpp:7:12]: (error) Allocation with f2, assert doesn't release it. [leakNoVarFunctionCall]\n" "[test.cpp:8:12]: (error) Allocation with f3, assert doesn't release it. [leakNoVarFunctionCall]\n", errout_str()); + check("struct S {\n" + " explicit S(int fd) {\n" + " m_fd = fd;\n" + " }\n" + " ~S() {\n" + " if (m_fd >= 0)\n" + " close(m_fd); \n" + " }\n" + " int m_fd = -1;\n" + "};\n" + "S g(char *name) {\n" + " return S(mkostemp(name, 0));\n" + "}\n" + "void f(char* ptr) {\n" + " S s = g(ptr);\n" + "}\n"); + ASSERT_EQUALS("", errout_str()); } void missingAssignment() { From 960641ad636f4515f2b3b6eb84c9a44cab8d4f0f Mon Sep 17 00:00:00 2001 From: Aaron Danen Date: Wed, 29 Jul 2026 12:15:34 -0700 Subject: [PATCH 2/4] remove temp comment --- lib/checkmemoryleak.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 2af137ccce9..4496055db7b 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -1046,7 +1046,6 @@ void CheckMemoryLeakNoVarImpl::checkForUnreleasedInputArgument(const Scope *scop const AllocType alloc = getAllocationType(arg, 0); if (alloc == No) continue; - //if (alloc == New || alloc == NewArray) { else { const Token* typeTok = arg->next(); bool bail = !typeTok->isStandardType() && From 9590471d8c46875e09c1ebe8451803dbf3373896 Mon Sep 17 00:00:00 2001 From: Aaron Danen Date: Wed, 29 Jul 2026 19:50:03 -0700 Subject: [PATCH 3/4] remove else after continue --- lib/checkmemoryleak.cpp | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 4496055db7b..1fd2d52d7f5 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -1046,22 +1046,20 @@ void CheckMemoryLeakNoVarImpl::checkForUnreleasedInputArgument(const Scope *scop const AllocType alloc = getAllocationType(arg, 0); if (alloc == No) continue; - else { - const Token* typeTok = arg->next(); - bool bail = !typeTok->isStandardType() && - (!typeTok->valueType() || - (typeTok->valueType()->type < ValueType::Type::SMART_POINTER && - typeTok->valueType()->type != ValueType::Type::POD)) && - !mSettings.library.detectContainerOrIterator(typeTok) && - !mSettings.library.podtype(typeTok->expressionString()); - if (bail && typeTok->type() && typeTok->type()->classScope && - typeTok->type()->classScope->numConstructors == 0 && - typeTok->type()->classScope->getDestructor() == nullptr) { - bail = false; - } - if (bail) - continue; + const Token* typeTok = arg->next(); + bool bail = !typeTok->isStandardType() && + (!typeTok->valueType() || + (typeTok->valueType()->type < ValueType::Type::SMART_POINTER && + typeTok->valueType()->type != ValueType::Type::POD)) && + !mSettings.library.detectContainerOrIterator(typeTok) && + !mSettings.library.podtype(typeTok->expressionString()); + if (bail && typeTok->type() && typeTok->type()->classScope && + typeTok->type()->classScope->numConstructors == 0 && + typeTok->type()->classScope->getDestructor() == nullptr) { + bail = false; } + if (bail) + continue; if (isReopenStandardStream(arg)) continue; if (tok->function()) { From b8feb14bf0af988be48326e04379d8bcbd603daa Mon Sep 17 00:00:00 2001 From: Aaron Danen Date: Thu, 30 Jul 2026 08:24:58 -0700 Subject: [PATCH 4/4] revert check for alloc in ctor --- lib/checkmemoryleak.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 1fd2d52d7f5..d4024865dc1 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -517,7 +517,7 @@ void CheckMemoryLeakInClassImpl::check() // only check classes and structures for (const Scope * scope : symbolDatabase->classAndStructScopes) { for (const Variable &var : scope->varlist) { - if (!var.isStatic()) { + if (!var.isStatic() && (var.isPointer() || var.isPointerArray())) { // allocation but no deallocation of private variables in public function.. const Token *tok = var.typeStartToken(); // Either it is of standard type or a non-derived type