Skip to content

Commit

Permalink
Fix #11866 FN memleak when pointer is converted to bool (danmar#5306)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrchr-github authored Aug 10, 2023
1 parent de9795b commit 23deadb
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 5 deletions.
4 changes: 2 additions & 2 deletions cfg/windows.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3699,7 +3699,7 @@ HFONT CreateFont(
<noreturn>false</noreturn>
<returnValue type="DWORD"/>
<leak-ignore/>
<arg nr="1" direction="in">
<arg nr="1">
<not-uninit/>
</arg>
<arg nr="2" direction="in">
Expand Down Expand Up @@ -3746,7 +3746,7 @@ HFONT CreateFont(
<use-retval/>
<noreturn>false</noreturn>
<returnValue type="HRSRC"/>
<arg nr="1" direction="in">
<arg nr="1">
<not-uninit/>
</arg>
<arg nr="2" direction="in">
Expand Down
26 changes: 23 additions & 3 deletions lib/checkmemoryleak.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -968,11 +968,13 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope)

if (Token::simpleMatch(tok->next()->astParent(), "(")) // passed to another function
continue;
if (!tok->isKeyword() && (mSettings->library.isNotLibraryFunction(tok) || !mSettings->library.isLeakIgnore(functionName)))
if (!tok->isKeyword() && !tok->function() && !mSettings->library.isLeakIgnore(functionName))
continue;

const std::vector<const Token *> args = getArguments(tok);
int argnr = -1;
for (const Token* arg : args) {
++argnr;
if (arg->isOp() && !(tok->isKeyword() && arg->str() == "*")) // e.g. switch (*new int)
continue;
while (arg->astOperand1()) {
Expand All @@ -983,10 +985,28 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope)
const AllocType alloc = getAllocationType(arg, 0);
if (alloc == No)
continue;
if ((alloc == New || alloc == NewArray) && arg->next() && !(arg->next()->isStandardType() || mSettings->library.detectContainerOrIterator(arg)))
continue;
if (alloc == New || alloc == NewArray) {
const Token* typeTok = arg->next();
bool bail = !typeTok->isStandardType() &&
!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()) {
const Variable* argvar = tok->function()->getArgumentVar(argnr);
if (!argvar || !argvar->valueType())
continue;
if (argvar->valueType()->typeSize(mSettings->platform, /*p*/ true) >= mSettings->platform.sizeof_pointer)
continue;
}
functionCallLeak(arg, arg->str(), functionName);
}

Expand Down
37 changes: 37 additions & 0 deletions test/testmemleak.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2456,6 +2456,43 @@ class TestMemleakNoVar : public TestFixture {
" s->p = s->p ? strcpy(new char[N], s->p) : nullptr;\n"
"};\n");
ASSERT_EQUALS("", errout.str());

check("struct S {};\n" // #11866
"void f(bool b);\n"
"void g() {\n"
" f(new int());\n"
" f(new std::vector<int>());\n"
" f(new S());\n"
" f(new tm());\n"
" f(malloc(sizeof(S)));\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Allocation with new, f doesn't release it.\n"
"[test.cpp:5]: (error) Allocation with new, f doesn't release it.\n"
"[test.cpp:6]: (error) Allocation with new, f doesn't release it.\n"
"[test.cpp:7]: (error) Allocation with new, f doesn't release it.\n"
"[test.cpp:8]: (error) Allocation with malloc, f doesn't release it.\n",
errout.str());

check("void f(uintptr_t u);\n"
"void g() {\n"
" f((uintptr_t)new int());\n"
"}\n");
ASSERT_EQUALS("", errout.str());

check("void f(uint8_t u);\n"
"void g() {\n"
" f((uint8_t)new int());\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (error) Allocation with new, f doesn't release it.\n",
errout.str());

check("void f(int i, T t);\n"
"void g(int i, U* u);\n"
"void h() {\n"
" f(1, new int());\n"
" g(1, new int());\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}

void missingAssignment() {
Expand Down

0 comments on commit 23deadb

Please sign in to comment.