Fix #11866 FN memleak when pointer is converted to bool (#5306)

This commit is contained in:
chrchr-github 2023-08-10 15:38:12 +02:00 committed by GitHub
parent de9795b07b
commit 23deadb370
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 5 deletions

View File

@ -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">
@ -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">

View File

@ -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()) {
@ -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);
}

View File

@ -2456,6 +2456,43 @@ private:
" 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() {