Fix #10905, #11665 FN deallocuse (#5751)

This commit is contained in:
chrchr-github 2023-12-23 11:31:27 +01:00 committed by GitHub
parent 7f0234e7d5
commit 17ee4093fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 6 deletions

View File

@ -466,6 +466,9 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
const Token * closingParenthesis = tok->linkAt(1);
for (const Token *innerTok = tok->tokAt(2); innerTok && innerTok != closingParenthesis; innerTok = innerTok->next()) {
// TODO: replace with checkTokenInsideExpression()
const Token* const openingPar = isFunctionCall(innerTok);
if (!openingPar)
checkTokenInsideExpression(innerTok, varInfo);
if (!isLocalVarNoAutoDealloc(innerTok, mTokenizer->isCPP()))
continue;
@ -502,7 +505,6 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
}
// check for function call
const Token * const openingPar = isFunctionCall(innerTok);
if (openingPar) {
const Library::AllocFunc* allocFunc = mSettings->library.getDeallocFuncInfo(innerTok);
// innerTok is a function name
@ -805,7 +807,8 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
const Token * vtok = typeEndTok->tokAt(3);
const VarInfo::AllocInfo allocation(af ? af->groupId : (arrayDelete ? NEW_ARRAY : NEW), VarInfo::OWNED, ftok);
changeAllocStatus(varInfo, allocation, vtok, vtok);
}
} else if (Token::Match(tok, "%var% ."))
checkTokenInsideExpression(tok, varInfo);
}
ret(endToken, varInfo, true);
return true;
@ -930,8 +933,7 @@ void CheckLeakAutoVar::changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocI
void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af)
{
// Ignore function call?
if (mSettings->library.isLeakIgnore(mSettings->library.getFunctionName(tokName)))
return;
const bool isLeakIgnore = mSettings->library.isLeakIgnore(mSettings->library.getFunctionName(tokName));
if (mSettings->library.getReallocFuncInfo(tokName))
return;
@ -990,6 +992,8 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin
varAlloc.allocTok = arg;
}
}
else if (isLeakIgnore)
checkTokenInsideExpression(arg, varInfo);
else
changeAllocStatus(varInfo, dealloc.type == 0 ? allocation : dealloc, tokName, arg);
}

View File

@ -859,7 +859,7 @@ void memleak_scandir(void)
which is allocated via malloc(3). If filter is NULL, all entries are
selected.*/
// TODO: cppcheck-suppress memleak
// cppcheck-suppress memleak
}
void no_memleak_scandir(void)

View File

@ -5202,6 +5202,16 @@ private:
" for (int i = 0; i < N; a[i++] = false);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void f() {\n" // #8192
" for (int i = 0; i > 10; ++i) {}\n"
"}\n");
TODO_ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'i>10' is always false\n", "", errout.str());
check("void f() {\n"
" for (int i = 1000; i < 20; ++i) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'i<20' is always false\n", errout.str());
}
void alwaysTrueTryCatch()

View File

@ -112,6 +112,7 @@ private:
TEST_CASE(deallocuse11); // #8302
TEST_CASE(deallocuse12);
TEST_CASE(deallocuse13);
TEST_CASE(deallocuse14);
TEST_CASE(doublefree1);
TEST_CASE(doublefree2);
@ -924,6 +925,25 @@ private:
errout.str());
}
void deallocuse14() {
check("struct S { void f(); };\n" // #10905
"void g() {\n"
" S* s = new S;\n"
" delete s;\n"
" s->f();\n"
"}\n", true);
ASSERT_EQUALS("[test.cpp:5]: (error) Dereferencing 's' after it is deallocated / released\n",
errout.str());
check("void f() {\n"
" int *p = (int*)malloc(4);\n"
" free(p);\n"
" if (*p == 5) {}\n"
"}\n");
ASSERT_EQUALS("[test.c:4]: (error) Dereferencing 'p' after it is deallocated / released\n",
errout.str());
}
void doublefree1() { // #3895
check("void f(char *p) {\n"
" if (x)\n"
@ -2996,7 +3016,14 @@ private:
" free(p);\n"
" strcpy(a, p);\n"
"}");
TODO_ASSERT_EQUALS("error (free,use)", "", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (error) Dereferencing 'p' after it is deallocated / released\n", errout.str());
check("void f(char *p, const char *q) {\n" // #11665
" free(p);\n"
" strcpy(p, q);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (error) Dereferencing 'p' after it is deallocated / released\n",
errout.str());
check("void f(char *p) {\n" // #3041 - assigning pointer when it's used
" free(p);\n"

View File

@ -6335,6 +6335,21 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:15] -> [test.cpp:17]: (warning) Uninitialized variable: pwd\n", errout.str());
valueFlowUninit("size_t Read(unsigned char* buffer, size_t len);\n" // #11540
"void f() {\n"
" const int N = 100;\n"
" uint8_t data[N];\n"
" size_t data_size = 0;\n"
" for (int i = 0; i < 10; i++) {\n"
" if (!data_size)\n"
" data_size = Read(data, N);\n"
" if (!data_size)\n"
" return;\n"
" if (data[0] == 0x47) {}\n"
" }\n"
"}\n");
ASSERT_EQUALS("", errout.str());
// #12033
valueFlowUninit("void g(const char*p);\n"
"void f() {\n"