Fix issue 9833: False positive: Division by zero when using pointer to struct
This commit is contained in:
parent
48a6852a4a
commit
75b955b9c6
|
@ -12,6 +12,7 @@ struct ForwardTraversal {
|
|||
enum class Progress { Continue, Break, Skip };
|
||||
ValuePtr<ForwardAnalyzer> analyzer;
|
||||
const Settings* settings;
|
||||
ForwardAnalyzer::Action actions;
|
||||
|
||||
std::pair<bool, bool> evalCond(const Token* tok) {
|
||||
std::vector<int> result = analyzer->evaluate(tok);
|
||||
|
@ -115,6 +116,7 @@ struct ForwardTraversal {
|
|||
|
||||
Progress update(Token* tok) {
|
||||
ForwardAnalyzer::Action action = analyzer->analyze(tok);
|
||||
actions |= action;
|
||||
if (!action.isNone())
|
||||
analyzer->update(tok, action);
|
||||
if (action.isInconclusive() && !analyzer->lowerToInconclusive())
|
||||
|
@ -225,6 +227,7 @@ struct ForwardTraversal {
|
|||
allAnalysis |= analyzeRecursive(initTok);
|
||||
if (stepTok)
|
||||
allAnalysis |= analyzeRecursive(stepTok);
|
||||
actions |= allAnalysis;
|
||||
if (allAnalysis.isInconclusive()) {
|
||||
if (!analyzer->lowerToInconclusive())
|
||||
return Progress::Break;
|
||||
|
@ -552,8 +555,9 @@ struct ForwardTraversal {
|
|||
|
||||
};
|
||||
|
||||
void valueFlowGenericForward(Token* start, const Token* end, const ValuePtr<ForwardAnalyzer>& fa, const Settings* settings)
|
||||
ForwardAnalyzer::Action valueFlowGenericForward(Token* start, const Token* end, const ValuePtr<ForwardAnalyzer>& fa, const Settings* settings)
|
||||
{
|
||||
ForwardTraversal ft{fa, settings};
|
||||
ft.updateRange(start, end);
|
||||
return ft.actions;
|
||||
}
|
||||
|
|
|
@ -113,6 +113,6 @@ struct ForwardAnalyzer {
|
|||
virtual ~ForwardAnalyzer() {}
|
||||
};
|
||||
|
||||
void valueFlowGenericForward(Token* start, const Token* end, const ValuePtr<ForwardAnalyzer>& fa, const Settings* settings);
|
||||
ForwardAnalyzer::Action valueFlowGenericForward(Token* start, const Token* end, const ValuePtr<ForwardAnalyzer>& fa, const Settings* settings);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1710,7 +1710,7 @@ static void valueFlowGlobalStaticVar(TokenList *tokenList, const Settings *setti
|
|||
}
|
||||
}
|
||||
|
||||
static void valueFlowForwardVariable(Token* const startToken,
|
||||
static ForwardAnalyzer::Action valueFlowForwardVariable(Token* const startToken,
|
||||
const Token* const endToken,
|
||||
const Variable* const var,
|
||||
std::list<ValueFlow::Value> values,
|
||||
|
@ -2697,7 +2697,7 @@ static std::vector<const Variable*> getAliasesFromValues(std::list<ValueFlow::Va
|
|||
return aliases;
|
||||
}
|
||||
|
||||
static void valueFlowForwardVariable(Token* const startToken,
|
||||
static ForwardAnalyzer::Action valueFlowForwardVariable(Token* const startToken,
|
||||
const Token* const endToken,
|
||||
const Variable* const var,
|
||||
std::list<ValueFlow::Value> values,
|
||||
|
@ -2705,20 +2705,22 @@ static void valueFlowForwardVariable(Token* const startToken,
|
|||
TokenList* const tokenlist,
|
||||
const Settings* const settings)
|
||||
{
|
||||
ForwardAnalyzer::Action actions;
|
||||
for (ValueFlow::Value& v : values) {
|
||||
VariableForwardAnalyzer a(var, v, aliases, tokenlist);
|
||||
valueFlowGenericForward(startToken, endToken, a, settings);
|
||||
actions |= valueFlowGenericForward(startToken, endToken, a, settings);
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
static void valueFlowForwardVariable(Token* const startToken,
|
||||
static ForwardAnalyzer::Action valueFlowForwardVariable(Token* const startToken,
|
||||
const Token* const endToken,
|
||||
const Variable* const var,
|
||||
std::list<ValueFlow::Value> values,
|
||||
TokenList* const tokenlist,
|
||||
const Settings* const settings)
|
||||
{
|
||||
valueFlowForwardVariable(startToken, endToken, var, std::move(values), getAliasesFromValues(values), tokenlist, settings);
|
||||
return valueFlowForwardVariable(startToken, endToken, var, std::move(values), getAliasesFromValues(values), tokenlist, settings);
|
||||
}
|
||||
|
||||
// Old deprecated version
|
||||
|
@ -2805,17 +2807,19 @@ struct ExpressionForwardAnalyzer : SingleValueFlowForwardAnalyzer {
|
|||
}
|
||||
};
|
||||
|
||||
static void valueFlowForwardExpression(Token* startToken,
|
||||
static ForwardAnalyzer::Action valueFlowForwardExpression(Token* startToken,
|
||||
const Token* endToken,
|
||||
const Token* exprTok,
|
||||
const std::list<ValueFlow::Value>& values,
|
||||
const TokenList* const tokenlist,
|
||||
const Settings* settings)
|
||||
{
|
||||
ForwardAnalyzer::Action actions;
|
||||
for (const ValueFlow::Value& v : values) {
|
||||
ExpressionForwardAnalyzer a(exprTok, v, tokenlist);
|
||||
valueFlowGenericForward(startToken, endToken, a, settings);
|
||||
actions |= valueFlowGenericForward(startToken, endToken, a, settings);
|
||||
}
|
||||
return actions;
|
||||
}
|
||||
|
||||
static const Token* parseBinaryIntOp(const Token* expr, MathLib::bigint& known)
|
||||
|
@ -2879,7 +2883,7 @@ static const Token* solveExprValues(const Token* expr, std::list<ValueFlow::Valu
|
|||
return expr;
|
||||
}
|
||||
|
||||
static void valueFlowForward(Token* startToken,
|
||||
static ForwardAnalyzer::Action valueFlowForward(Token* startToken,
|
||||
const Token* endToken,
|
||||
const Token* exprTok,
|
||||
std::list<ValueFlow::Value> values,
|
||||
|
@ -2888,14 +2892,14 @@ static void valueFlowForward(Token* startToken,
|
|||
{
|
||||
const Token* expr = solveExprValues(exprTok, values);
|
||||
if (expr->variable()) {
|
||||
valueFlowForwardVariable(startToken,
|
||||
return valueFlowForwardVariable(startToken,
|
||||
endToken,
|
||||
expr->variable(),
|
||||
values,
|
||||
tokenlist,
|
||||
settings);
|
||||
} else {
|
||||
valueFlowForwardExpression(startToken, endToken, expr, values, tokenlist, settings);
|
||||
return valueFlowForwardExpression(startToken, endToken, expr, values, tokenlist, settings);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4554,9 +4558,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist,
|
|||
const Token* vartok,
|
||||
const std::list<ValueFlow::Value>& values,
|
||||
bool) {
|
||||
valueFlowForward(start->next(), stop, vartok, values, tokenlist, settings);
|
||||
std::vector<const Variable*> vars = getExprVariables(vartok, tokenlist, symboldatabase, settings);
|
||||
return isVariablesChanged(start, stop, 0, vars, settings, tokenlist->isCPP());
|
||||
return valueFlowForward(start->next(), stop, vartok, values, tokenlist, settings).isModified();
|
||||
};
|
||||
handler.parse = [&](const Token *tok) {
|
||||
ValueFlowConditionHandler::Condition cond;
|
||||
|
@ -5887,19 +5889,19 @@ struct ContainerVariableForwardAnalyzer : VariableForwardAnalyzer {
|
|||
}
|
||||
};
|
||||
|
||||
static void valueFlowContainerForward(Token *tok, const Token* endToken, const Variable* var, ValueFlow::Value value, TokenList *tokenlist)
|
||||
static ForwardAnalyzer::Action valueFlowContainerForward(Token *tok, const Token* endToken, const Variable* var, ValueFlow::Value value, TokenList *tokenlist)
|
||||
{
|
||||
ContainerVariableForwardAnalyzer a(var, value, getAliasesFromValues({value}), tokenlist);
|
||||
valueFlowGenericForward(tok, endToken, a, tokenlist->getSettings());
|
||||
return valueFlowGenericForward(tok, endToken, a, tokenlist->getSettings());
|
||||
}
|
||||
static void valueFlowContainerForward(Token *tok, const Variable* var, ValueFlow::Value value, TokenList *tokenlist)
|
||||
static ForwardAnalyzer::Action valueFlowContainerForward(Token *tok, const Variable* var, ValueFlow::Value value, TokenList *tokenlist)
|
||||
{
|
||||
const Token * endOfVarScope = nullptr;
|
||||
if (var->isLocal() || var->isArgument())
|
||||
endOfVarScope = var->scope()->bodyEnd;
|
||||
if (!endOfVarScope)
|
||||
endOfVarScope = tok->scope()->bodyEnd;
|
||||
valueFlowContainerForward(tok, endOfVarScope, var, std::move(value), tokenlist);
|
||||
return valueFlowContainerForward(tok, endOfVarScope, var, std::move(value), tokenlist);
|
||||
}
|
||||
|
||||
static bool isContainerSizeChanged(const Token *tok, int depth)
|
||||
|
@ -6053,9 +6055,7 @@ static void valueFlowIteratorAfterCondition(TokenList *tokenlist,
|
|||
const Token* vartok,
|
||||
const std::list<ValueFlow::Value>& values,
|
||||
bool) {
|
||||
valueFlowForward(start->next(), stop, vartok, values, tokenlist, settings);
|
||||
std::vector<const Variable*> vars = getExprVariables(vartok, tokenlist, symboldatabase, settings);
|
||||
return isVariablesChanged(start, stop, 0, vars, settings, tokenlist->isCPP());
|
||||
return valueFlowForward(start->next(), stop, vartok, values, tokenlist, settings).isModified();
|
||||
};
|
||||
handler.parse = [&](const Token *tok) {
|
||||
ValueFlowConditionHandler::Condition cond;
|
||||
|
@ -6230,8 +6230,7 @@ static void valueFlowContainerAfterCondition(TokenList *tokenlist,
|
|||
const Variable* var = vartok->variable();
|
||||
if (!var)
|
||||
return false;
|
||||
valueFlowContainerForward(start->next(), stop, var, values.front(), tokenlist);
|
||||
return isContainerSizeChanged(var->declarationId(), start, stop);
|
||||
return valueFlowContainerForward(start->next(), stop, var, values.front(), tokenlist).isModified();
|
||||
};
|
||||
handler.parse = [&](const Token *tok) {
|
||||
ValueFlowConditionHandler::Condition cond;
|
||||
|
|
|
@ -697,6 +697,16 @@ private:
|
|||
" a = b / -x;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("struct A {\n"
|
||||
" int x;\n"
|
||||
"};\n"
|
||||
"int f(A* a) {\n"
|
||||
" if (a->x == 0) \n"
|
||||
" a->x = 1;\n"
|
||||
" return 1/a->x;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void nanInArithmeticExpression() {
|
||||
|
|
Loading…
Reference in New Issue