Skip to content

Commit 49897e6

Browse files
Fix #12354 FN memleak, uninitvar with member initializer (#6090)
1 parent ff14917 commit 49897e6

4 files changed

Lines changed: 48 additions & 5 deletions

File tree

lib/checkleakautovar.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,16 @@ static const std::array<std::pair<std::string, std::string>, 4> alloc_failed_con
6262
static const std::array<std::pair<std::string, std::string>, 4> alloc_success_conds {{{"!=", "0"}, {">", "0"}, {"!=", "-1"}, {">=", "0"}}};
6363

6464
static bool isAutoDeallocType(const Type* type) {
65-
if (!type)
65+
if (!type || !type->classScope)
6666
return true;
67-
if (type->classScope && type->classScope->numConstructors == 0 &&
68-
(type->classScope->varlist.empty() || type->needInitialization == Type::NeedInitialization::True) &&
69-
std::none_of(type->derivedFrom.cbegin(), type->derivedFrom.cend(), [](const Type::BaseInfo& bi) {
67+
if (type->classScope->numConstructors > 0)
68+
return true;
69+
const std::list<Variable>& varlist = type->classScope->varlist;
70+
if (std::any_of(varlist.begin(), varlist.end(), [](const Variable& v) {
71+
return !v.valueType() || (!v.valueType()->isPrimitive() && !v.valueType()->container);
72+
}))
73+
return true;
74+
if (std::none_of(type->derivedFrom.cbegin(), type->derivedFrom.cend(), [](const Type::BaseInfo& bi) {
7075
return isAutoDeallocType(bi.type);
7176
}))
7277
return false;

lib/valueflow.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8084,7 +8084,8 @@ static void valueFlowUninit(TokenList& tokenlist, ErrorLogger* const errorLogger
80848084
if (memVar.isArray())
80858085
continue;
80868086
if (!needsInitialization(&memVar, tokenlist.isCPP())) {
8087-
partial = true;
8087+
if (!var->isPointer())
8088+
partial = true;
80888089
continue;
80898090
}
80908091
MemberExpressionAnalyzer analyzer(memVar.nameToken()->str(), tok, uninitValue, tokenlist, settings);

test/testleakautovar.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,17 @@ class TestLeakAutoVar : public TestFixture {
672672
" if (d) {}\n"
673673
"}", /*cpp*/ true);
674674
ASSERT_EQUALS("[test.cpp:6]: (error) Memory leak: d\n", errout.str());
675+
676+
check("struct S {\n" // #12354
677+
" int i{};\n"
678+
" void f();\n"
679+
"};\n"
680+
"void f(S* p, bool b) {\n"
681+
" if (b)\n"
682+
" p = new S();\n"
683+
" p->f();\n"
684+
"}", /*cpp*/ true);
685+
ASSERT_EQUALS("[test.cpp:9]: (error) Memory leak: p\n", errout.str());
675686
}
676687

677688
void realloc1() {
@@ -3125,6 +3136,7 @@ class TestLeakAutoVarStrcpy : public TestFixture {
31253136
TEST_CASE(fclose_false_positive); // #9575
31263137
TEST_CASE(strcpy_false_negative);
31273138
TEST_CASE(doubleFree);
3139+
TEST_CASE(memleak_std_string);
31283140
}
31293141

31303142
void returnedValue() { // #9298
@@ -3179,6 +3191,19 @@ class TestLeakAutoVarStrcpy : public TestFixture {
31793191
"}\n");
31803192
ASSERT_EQUALS("", errout.str());
31813193
}
3194+
3195+
void memleak_std_string() {
3196+
check("struct S {\n" // #12354
3197+
" std::string s;\n"
3198+
" void f();\n"
3199+
"};\n"
3200+
"void f(S* p, bool b) {\n"
3201+
" if (b)\n"
3202+
" p = new S();\n"
3203+
" p->f();\n"
3204+
"}");
3205+
ASSERT_EQUALS("[test.cpp:9]: (error) Memory leak: p\n", errout.str());
3206+
}
31823207
};
31833208

31843209
REGISTER_TEST(TestLeakAutoVarStrcpy)

test/testuninitvar.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7394,6 +7394,18 @@ class TestUninitVar : public TestFixture {
73947394
" S s(&p);\n"
73957395
"}\n");
73967396
ASSERT_EQUALS("", errout.str());
7397+
7398+
valueFlowUninit("struct S {\n" // #12354
7399+
" int i{};\n"
7400+
" void f();\n"
7401+
"};\n"
7402+
"void f(bool b) {\n"
7403+
" S* p;\n"
7404+
" if (b)\n"
7405+
" p = new S();\n"
7406+
" p->f();\n"
7407+
"}\n");
7408+
ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:9]: (warning) Uninitialized variable: p\n", errout.str());
73977409
}
73987410

73997411
void uninitvar_memberfunction() {

0 commit comments

Comments
 (0)