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);
|
"$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)
|
static bool isLeafDot(const Token* tok)
|
||||||
{
|
{
|
||||||
if (!tok)
|
if (!tok)
|
||||||
|
@ -1557,12 +1573,14 @@ void CheckUninitVar::valueFlowUninit()
|
||||||
if (Token::Match(tok->astParent(), ". %var%") && !isleaf)
|
if (Token::Match(tok->astParent(), ". %var%") && !isleaf)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!isUsedByFunction(tok, v->indirect, mSettings)) {
|
||||||
if (!(Token::Match(tok->astParent(), ". %name% (") && uninitderef) &&
|
if (!(Token::Match(tok->astParent(), ". %name% (") && uninitderef) &&
|
||||||
isVariableChanged(tok, v->indirect, mSettings, mTokenizer->isCPP()))
|
isVariableChanged(tok, v->indirect, mSettings, mTokenizer->isCPP()))
|
||||||
continue;
|
continue;
|
||||||
bool inconclusive = false;
|
bool inconclusive = false;
|
||||||
if (isVariableChangedByFunctionCall(tok, v->indirect, mSettings, &inconclusive) || inconclusive)
|
if (isVariableChangedByFunctionCall(tok, v->indirect, mSettings, &inconclusive) || inconclusive)
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
uninitvarError(tok, tok->expressionString(), v->errorPath);
|
uninitvarError(tok, tok->expressionString(), v->errorPath);
|
||||||
ids.insert(tok->exprId());
|
ids.insert(tok->exprId());
|
||||||
if (v->tokvalue)
|
if (v->tokvalue)
|
||||||
|
|
|
@ -4400,6 +4400,47 @@ private:
|
||||||
|
|
||||||
|
|
||||||
void valueFlowUninit() {
|
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"
|
valueFlowUninit("void f() {\n"
|
||||||
" int x;\n"
|
" int x;\n"
|
||||||
" switch (x) {}\n"
|
" switch (x) {}\n"
|
||||||
|
|
Loading…
Reference in New Issue