Skip to content

Commit

Permalink
Fix #11866 FN memleak when pointer is converted to bool
Browse files Browse the repository at this point in the history
  • Loading branch information
chrchr-github committed Aug 9, 2023
1 parent 9ed6a4f commit ea59b5b
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 3 deletions.
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
28 changes: 28 additions & 0 deletions test/testmemleak.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2456,6 +2456,34 @@ 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("", errout.str());
}

void missingAssignment() {
Expand Down

0 comments on commit ea59b5b

Please sign in to comment.