Fix #11758 Regression: memleak / Fix #11746 FN: deallocuse (#5139)

* Fix #11758 Regression: memleak

* Format

* Fix #11746 FN: deallocuse

* Complete the trifecta
This commit is contained in:
chrchr-github 2023-06-10 00:24:36 +02:00 committed by GitHub
parent 22e67d3534
commit 69116c8386
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 5 deletions

View File

@ -1051,7 +1051,7 @@ void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndO
// don't warn if we leave an inner scope // don't warn if we leave an inner scope
if (isEndOfScope && var->scope() && tok != var->scope()->bodyEnd) if (isEndOfScope && var->scope() && tok != var->scope()->bodyEnd)
continue; continue;
bool used = false; enum class PtrUsage { NONE, DEREF, PTR } used = PtrUsage::NONE;
for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) {
if (tok2->str() == ";") if (tok2->str() == ";")
break; break;
@ -1068,19 +1068,25 @@ void CheckLeakAutoVar::ret(const Token *tok, VarInfo &varInfo, const bool isEndO
tok2 = tok3->next(); tok2 = tok3->next();
else if (Token::Match(tok3, "& %varid% . %name%", varid)) else if (Token::Match(tok3, "& %varid% . %name%", varid))
tok2 = tok3->tokAt(4); tok2 = tok3->tokAt(4);
else if (Token::simpleMatch(tok3, "*"))
tok2 = tok3;
else else
continue; continue;
if (Token::Match(tok2, "[});,+[]")) { if (Token::Match(tok2, "[});,+]")) {
used = true; used = PtrUsage::PTR;
break;
}
if (Token::Match(tok2, "[|.|*")) {
used = PtrUsage::DEREF;
break; break;
} }
} }
// return deallocated pointer // return deallocated pointer
if (used && it->second.status == VarInfo::DEALLOC) if (used != PtrUsage::NONE && it->second.status == VarInfo::DEALLOC)
deallocReturnError(tok, it->second.allocTok, var->name()); deallocReturnError(tok, it->second.allocTok, var->name());
else if (!used && !it->second.managed() && !var->isReference()) { else if (used != PtrUsage::PTR && !it->second.managed() && !var->isReference()) {
const auto use = possibleUsage.find(varid); const auto use = possibleUsage.find(varid);
if (use == possibleUsage.end()) { if (use == possibleUsage.end()) {
leakError(tok, var->name(), it->second.type); leakError(tok, var->name(), it->second.type);

View File

@ -194,6 +194,7 @@ private:
TEST_CASE(return7); // #9343 return (uint8_t*)x TEST_CASE(return7); // #9343 return (uint8_t*)x
TEST_CASE(return8); TEST_CASE(return8);
TEST_CASE(return9); TEST_CASE(return9);
TEST_CASE(return10);
// General tests: variable type, allocation type, etc // General tests: variable type, allocation type, etc
TEST_CASE(test1); TEST_CASE(test1);
@ -2392,6 +2393,30 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void return10() {
check("char f() {\n" // #11758
" char* p = (char*)malloc(1);\n"
" p[0] = 'x';\n"
" return p[0];\n"
"}");
ASSERT_EQUALS("[test.c:4]: (error) Memory leak: p\n", errout.str());
check("struct S { int f(); };\n" // #11746
"int g() {\n"
" S* s = new S;\n"
" delete s;\n"
" return s->f();\n"
"}", true);
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5]: (error) Returning/dereferencing 's' after it is deallocated / released\n", errout.str());
check("int f() {\n"
" int* p = new int(3);\n"
" delete p;\n"
" return *p;\n"
"}", true);
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (error) Returning/dereferencing 'p' after it is deallocated / released\n", errout.str());
}
void test1() { void test1() {
check("void f(double*&p) {\n" // 3809 check("void f(double*&p) {\n" // 3809
" p = malloc(0x100);\n" " p = malloc(0x100);\n"