Fix 10226: FN: knownConditionTrueFalse (#3537)

This commit is contained in:
Paul Fultz II 2021-10-31 08:51:07 -05:00 committed by GitHub
parent 3e6540c4b3
commit df59b07ba1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 4 deletions

View File

@ -5493,6 +5493,32 @@ ValueFlow::Value inferCondition(std::string op, MathLib::bigint val, const Token
return ValueFlow::Value{}; return ValueFlow::Value{};
} }
struct IteratorInferModel : InferModel {
virtual ValueFlow::Value::ValueType getType() const = 0;
virtual bool match(const ValueFlow::Value& value) const OVERRIDE {
return value.valueType == getType();
}
virtual ValueFlow::Value yield(MathLib::bigint value) const OVERRIDE
{
ValueFlow::Value result(value);
result.valueType = getType();
result.setKnown();
return result;
}
};
struct EndIteratorInferModel : IteratorInferModel {
virtual ValueFlow::Value::ValueType getType() const OVERRIDE {
return ValueFlow::Value::ValueType::ITERATOR_END;
}
};
struct StartIteratorInferModel : IteratorInferModel {
virtual ValueFlow::Value::ValueType getType() const OVERRIDE {
return ValueFlow::Value::ValueType::ITERATOR_END;
}
};
static void valueFlowInferCondition(TokenList* tokenlist, static void valueFlowInferCondition(TokenList* tokenlist,
const Settings* settings) const Settings* settings)
{ {
@ -5511,6 +5537,17 @@ static void valueFlowInferCondition(TokenList* tokenlist,
value.bound = ValueFlow::Value::Bound::Point; value.bound = ValueFlow::Value::Bound::Point;
setTokenValue(tok, value, settings); setTokenValue(tok, value, settings);
} else if (Token::Match(tok, "%comp%|-") && tok->astOperand1() && tok->astOperand2()) { } else if (Token::Match(tok, "%comp%|-") && tok->astOperand1() && tok->astOperand2()) {
if (astIsIterator(tok->astOperand1()) || astIsIterator(tok->astOperand2())) {
for (ValuePtr<InferModel> model :
std::vector<ValuePtr<InferModel>>{EndIteratorInferModel{}, StartIteratorInferModel{}}) {
std::vector<ValueFlow::Value> result =
infer(model, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values());
for (ValueFlow::Value value : result) {
value.valueType = ValueFlow::Value::ValueType::INT;
setTokenValue(tok, value, settings);
}
}
} else {
std::vector<ValueFlow::Value> result = std::vector<ValueFlow::Value> result =
infer(IntegralInferModel{}, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values()); infer(IntegralInferModel{}, tok->str(), tok->astOperand1()->values(), tok->astOperand2()->values());
for (const ValueFlow::Value& value : result) { for (const ValueFlow::Value& value : result) {
@ -5519,6 +5556,7 @@ static void valueFlowInferCondition(TokenList* tokenlist,
} }
} }
} }
}
struct SymbolicConditionHandler : SimpleConditionHandler { struct SymbolicConditionHandler : SimpleConditionHandler {
virtual std::vector<Condition> parse(const Token* tok, const Settings*) const OVERRIDE virtual std::vector<Condition> parse(const Token* tok, const Settings*) const OVERRIDE

View File

@ -4115,6 +4115,16 @@ private:
" if( s.size() < 3 ) return;\n" " if( s.size() < 3 ) return;\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// #10226
check("int f(std::vector<int>::iterator it, const std::vector<int>& vector) {\n"
" if (!(it != vector.end() && it != vector.begin()))\n"
" throw 0;\n"
" if (it != vector.end() && *it == 0)\n"
" return -1;\n"
" return *it;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (style) Condition 'it!=vector.end()' is always true\n", errout.str());
} }
void alwaysTrueLoop() void alwaysTrueLoop()