Skip to content

Commit 17ee409

Browse files
Fix #10905, #11665 FN deallocuse (danmar#5751)
1 parent 7f0234e commit 17ee409

File tree

5 files changed

+62
-6
lines changed

5 files changed

+62
-6
lines changed

lib/checkleakautovar.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,9 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
466466
const Token * closingParenthesis = tok->linkAt(1);
467467
for (const Token *innerTok = tok->tokAt(2); innerTok && innerTok != closingParenthesis; innerTok = innerTok->next()) {
468468
// TODO: replace with checkTokenInsideExpression()
469+
const Token* const openingPar = isFunctionCall(innerTok);
470+
if (!openingPar)
471+
checkTokenInsideExpression(innerTok, varInfo);
469472

470473
if (!isLocalVarNoAutoDealloc(innerTok, mTokenizer->isCPP()))
471474
continue;
@@ -502,7 +505,6 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
502505
}
503506

504507
// check for function call
505-
const Token * const openingPar = isFunctionCall(innerTok);
506508
if (openingPar) {
507509
const Library::AllocFunc* allocFunc = mSettings->library.getDeallocFuncInfo(innerTok);
508510
// innerTok is a function name
@@ -805,7 +807,8 @@ bool CheckLeakAutoVar::checkScope(const Token * const startToken,
805807
const Token * vtok = typeEndTok->tokAt(3);
806808
const VarInfo::AllocInfo allocation(af ? af->groupId : (arrayDelete ? NEW_ARRAY : NEW), VarInfo::OWNED, ftok);
807809
changeAllocStatus(varInfo, allocation, vtok, vtok);
808-
}
810+
} else if (Token::Match(tok, "%var% ."))
811+
checkTokenInsideExpression(tok, varInfo);
809812
}
810813
ret(endToken, varInfo, true);
811814
return true;
@@ -930,8 +933,7 @@ void CheckLeakAutoVar::changeAllocStatus(VarInfo &varInfo, const VarInfo::AllocI
930933
void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpeningPar, VarInfo &varInfo, const VarInfo::AllocInfo& allocation, const Library::AllocFunc* af)
931934
{
932935
// Ignore function call?
933-
if (mSettings->library.isLeakIgnore(mSettings->library.getFunctionName(tokName)))
934-
return;
936+
const bool isLeakIgnore = mSettings->library.isLeakIgnore(mSettings->library.getFunctionName(tokName));
935937
if (mSettings->library.getReallocFuncInfo(tokName))
936938
return;
937939

@@ -990,6 +992,8 @@ void CheckLeakAutoVar::functionCall(const Token *tokName, const Token *tokOpenin
990992
varAlloc.allocTok = arg;
991993
}
992994
}
995+
else if (isLeakIgnore)
996+
checkTokenInsideExpression(arg, varInfo);
993997
else
994998
changeAllocStatus(varInfo, dealloc.type == 0 ? allocation : dealloc, tokName, arg);
995999
}

test/cfg/posix.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,7 @@ void memleak_scandir(void)
859859
which is allocated via malloc(3). If filter is NULL, all entries are
860860
selected.*/
861861

862-
// TODO: cppcheck-suppress memleak
862+
// cppcheck-suppress memleak
863863
}
864864

865865
void no_memleak_scandir(void)

test/testcondition.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5202,6 +5202,16 @@ class TestCondition : public TestFixture {
52025202
" for (int i = 0; i < N; a[i++] = false);\n"
52035203
"}\n");
52045204
ASSERT_EQUALS("", errout.str());
5205+
5206+
check("void f() {\n" // #8192
5207+
" for (int i = 0; i > 10; ++i) {}\n"
5208+
"}\n");
5209+
TODO_ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'i>10' is always false\n", "", errout.str());
5210+
5211+
check("void f() {\n"
5212+
" for (int i = 1000; i < 20; ++i) {}\n"
5213+
"}\n");
5214+
ASSERT_EQUALS("[test.cpp:2]: (style) Condition 'i<20' is always false\n", errout.str());
52055215
}
52065216

52075217
void alwaysTrueTryCatch()

test/testleakautovar.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ class TestLeakAutoVar : public TestFixture {
112112
TEST_CASE(deallocuse11); // #8302
113113
TEST_CASE(deallocuse12);
114114
TEST_CASE(deallocuse13);
115+
TEST_CASE(deallocuse14);
115116

116117
TEST_CASE(doublefree1);
117118
TEST_CASE(doublefree2);
@@ -924,6 +925,25 @@ class TestLeakAutoVar : public TestFixture {
924925
errout.str());
925926
}
926927

928+
void deallocuse14() {
929+
check("struct S { void f(); };\n" // #10905
930+
"void g() {\n"
931+
" S* s = new S;\n"
932+
" delete s;\n"
933+
" s->f();\n"
934+
"}\n", true);
935+
ASSERT_EQUALS("[test.cpp:5]: (error) Dereferencing 's' after it is deallocated / released\n",
936+
errout.str());
937+
938+
check("void f() {\n"
939+
" int *p = (int*)malloc(4);\n"
940+
" free(p);\n"
941+
" if (*p == 5) {}\n"
942+
"}\n");
943+
ASSERT_EQUALS("[test.c:4]: (error) Dereferencing 'p' after it is deallocated / released\n",
944+
errout.str());
945+
}
946+
927947
void doublefree1() { // #3895
928948
check("void f(char *p) {\n"
929949
" if (x)\n"
@@ -2996,7 +3016,14 @@ class TestLeakAutoVarStrcpy : public TestFixture {
29963016
" free(p);\n"
29973017
" strcpy(a, p);\n"
29983018
"}");
2999-
TODO_ASSERT_EQUALS("error (free,use)", "", errout.str());
3019+
ASSERT_EQUALS("[test.cpp:3]: (error) Dereferencing 'p' after it is deallocated / released\n", errout.str());
3020+
3021+
check("void f(char *p, const char *q) {\n" // #11665
3022+
" free(p);\n"
3023+
" strcpy(p, q);\n"
3024+
"}\n");
3025+
ASSERT_EQUALS("[test.cpp:3]: (error) Dereferencing 'p' after it is deallocated / released\n",
3026+
errout.str());
30003027

30013028
check("void f(char *p) {\n" // #3041 - assigning pointer when it's used
30023029
" free(p);\n"

test/testuninitvar.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6335,6 +6335,21 @@ class TestUninitVar : public TestFixture {
63356335
"}");
63366336
ASSERT_EQUALS("[test.cpp:15] -> [test.cpp:17]: (warning) Uninitialized variable: pwd\n", errout.str());
63376337

6338+
valueFlowUninit("size_t Read(unsigned char* buffer, size_t len);\n" // #11540
6339+
"void f() {\n"
6340+
" const int N = 100;\n"
6341+
" uint8_t data[N];\n"
6342+
" size_t data_size = 0;\n"
6343+
" for (int i = 0; i < 10; i++) {\n"
6344+
" if (!data_size)\n"
6345+
" data_size = Read(data, N);\n"
6346+
" if (!data_size)\n"
6347+
" return;\n"
6348+
" if (data[0] == 0x47) {}\n"
6349+
" }\n"
6350+
"}\n");
6351+
ASSERT_EQUALS("", errout.str());
6352+
63386353
// #12033
63396354
valueFlowUninit("void g(const char*p);\n"
63406355
"void f() {\n"

0 commit comments

Comments
 (0)