Bug hunting; Avoid uninit false positives with simple analysis

This commit is contained in:
Daniel Marjamäki 2020-07-17 09:05:38 +02:00
parent 9af288e1dd
commit 592637af61
1 changed files with 36 additions and 8 deletions

View File

@ -157,6 +157,39 @@ static void integerOverflow(const Token *tok, const ExprEngine::Value &value, Ex
}
#endif
/** check if variable is unconditionally assigned */
static bool isVariableAssigned(const Variable *var, const Token *tok, const Token *scopeStart=nullptr)
{
const Token * const start = scopeStart && precedes(var->nameToken(), scopeStart) ? scopeStart : var->nameToken();
for (const Token *prev = tok->previous(); prev; prev = prev->previous()) {
if (!precedes(start, prev))
break;
if (prev->str() == "}") {
if (Token::simpleMatch(prev->link()->tokAt(-2), "} else {")) {
const Token *elseEnd = prev;
const Token *elseStart = prev->link();
const Token *ifEnd = elseStart->tokAt(-2);
const Token *ifStart = ifEnd->link();
if (isVariableAssigned(var, ifEnd, ifStart) && isVariableAssigned(var, elseEnd, elseStart)) {
return true;
}
}
prev = prev->link();
}
if (scopeStart && Token::Match(prev, "return|throw|continue|break"))
return true;
if (Token::Match(prev, "%varid% =", var->declarationId()))
return true;
// bailout; if variable is used previously that is checked first
if (!scopeStart && prev->varId() == var->declarationId())
return true;
}
return false;
}
static void uninit(const Token *tok, const ExprEngine::Value &value, ExprEngine::DataBase *dataBase)
{
if (!tok->astParent())
@ -256,16 +289,11 @@ static void uninit(const Token *tok, const ExprEngine::Value &value, ExprEngine:
// Are there unconditional assignment?
if (var && Token::Match(var->nameToken(), "%varid% ;| %varid%| =", tok->varId()))
return;
for (const Token *prev = tok->previous(); prev; prev = prev->previous()) {
if (!precedes(var->nameToken(), prev))
break;
if (prev->str() == "}")
prev = prev->link();
if (Token::Match(prev, "%varid% =", tok->varId()))
return;
}
}
if (tok->variable() && isVariableAssigned(tok->variable(), tok))
return;
// Uninitialized function argument
bool inconclusive = false;
if (Token::Match(tok->astParent(), "[,(]")) {