parent
7f0234e7d5
commit
17ee4093fa
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue