Check if uninit value is used in library function (#3516)

This commit is contained in:
Paul Fultz II 2021-10-20 13:51:59 -05:00 committed by GitHub
parent ba777b54d1
commit 257efb4019
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 6 deletions

View File

@ -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)

View File

@ -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"