Check if uninit value is used in library function (#3516)
This commit is contained in:
parent
ba777b54d1
commit
257efb4019
|
@ -1492,6 +1492,22 @@ void CheckUninitVar::uninitStructMemberError(const Token *tok, const std::string
|
|||
"$symbol:" + membername + "\nUninitialized struct member: $symbol", CWE_USE_OF_UNINITIALIZED_VARIABLE, Certainty::normal);
|
||||
}
|
||||
|
||||
static bool isUsedByFunction(const Token* tok, int indirect, const Settings* settings)
|
||||
{
|
||||
const bool addressOf = tok->astParent() && tok->astParent()->isUnaryOp("&");
|
||||
|
||||
int argnr;
|
||||
const Token* ftok = getTokenArgumentFunction(tok, argnr);
|
||||
if (!ftok)
|
||||
return false;
|
||||
const bool isnullbad = settings->library.isnullargbad(ftok, argnr + 1);
|
||||
if (indirect == 0 && astIsPointer(tok) && !addressOf && isnullbad)
|
||||
return true;
|
||||
bool hasIndirect = false;
|
||||
const bool isuninitbad = settings->library.isuninitargbad(ftok, argnr + 1, indirect, &hasIndirect);
|
||||
return isuninitbad && (!addressOf || isnullbad);
|
||||
}
|
||||
|
||||
static bool isLeafDot(const Token* tok)
|
||||
{
|
||||
if (!tok)
|
||||
|
@ -1557,12 +1573,14 @@ void CheckUninitVar::valueFlowUninit()
|
|||
if (Token::Match(tok->astParent(), ". %var%") && !isleaf)
|
||||
continue;
|
||||
}
|
||||
if (!(Token::Match(tok->astParent(), ". %name% (") && uninitderef) &&
|
||||
isVariableChanged(tok, v->indirect, mSettings, mTokenizer->isCPP()))
|
||||
continue;
|
||||
bool inconclusive = false;
|
||||
if (isVariableChangedByFunctionCall(tok, v->indirect, mSettings, &inconclusive) || inconclusive)
|
||||
continue;
|
||||
if (!isUsedByFunction(tok, v->indirect, mSettings)) {
|
||||
if (!(Token::Match(tok->astParent(), ". %name% (") && uninitderef) &&
|
||||
isVariableChanged(tok, v->indirect, mSettings, mTokenizer->isCPP()))
|
||||
continue;
|
||||
bool inconclusive = false;
|
||||
if (isVariableChangedByFunctionCall(tok, v->indirect, mSettings, &inconclusive) || inconclusive)
|
||||
continue;
|
||||
}
|
||||
uninitvarError(tok, tok->expressionString(), v->errorPath);
|
||||
ids.insert(tok->exprId());
|
||||
if (v->tokvalue)
|
||||
|
|
|
@ -4400,6 +4400,47 @@ private:
|
|||
|
||||
|
||||
void valueFlowUninit() {
|
||||
// Ticket #2207 - False negative
|
||||
valueFlowUninit("void foo() {\n"
|
||||
" int a;\n"
|
||||
" b = c - a;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
|
||||
|
||||
valueFlowUninit("void foo() {\n"
|
||||
" int a;\n"
|
||||
" b = a - c;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
|
||||
|
||||
// Ticket #6455 - some compilers allow const variables to be uninitialized
|
||||
// extracttests.disable
|
||||
valueFlowUninit("void foo() {\n"
|
||||
" const int a;\n"
|
||||
" b = c - a;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
|
||||
// extracttests.enable
|
||||
|
||||
valueFlowUninit("void foo() {\n"
|
||||
" int *p;\n"
|
||||
" realloc(p,10);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: p\n", errout.str());
|
||||
|
||||
valueFlowUninit("void foo() {\n" // #5240
|
||||
" char *p = malloc(100);\n"
|
||||
" char *tmp = realloc(p,1000);\n"
|
||||
" if (!tmp) free(p);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
valueFlowUninit("void foo() {\n"
|
||||
" int *p = NULL;\n"
|
||||
" realloc(p,10);\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
valueFlowUninit("void f() {\n"
|
||||
" int x;\n"
|
||||
" switch (x) {}\n"
|
||||
|
|
Loading…
Reference in New Issue