Fix 10437: FP knownConditionTrueFalse after pointer check (#3646)

This commit is contained in:
Paul Fultz II 2021-12-20 00:28:40 -06:00 committed by GitHub
parent a3560aaf5a
commit 73f24b43f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 31 deletions

View File

@ -128,34 +128,32 @@ void ProgramMemory::insert(const ProgramMemory &pm)
values.insert(p);
}
bool conditionIsFalse(const Token *condition, const ProgramMemory &programMemory)
bool evaluateCondition(const std::string& op,
MathLib::bigint r,
const Token* condition,
ProgramMemory& pm,
const Settings* settings)
{
if (!condition)
return false;
if (condition->str() == "&&") {
return conditionIsFalse(condition->astOperand1(), programMemory) ||
conditionIsFalse(condition->astOperand2(), programMemory);
if (condition->str() == op) {
return evaluateCondition(op, r, condition->astOperand1(), pm, settings) ||
evaluateCondition(op, r, condition->astOperand2(), pm, settings);
}
ProgramMemory progmem(programMemory);
MathLib::bigint result = 0;
bool error = false;
execute(condition, &progmem, &result, &error);
return !error && result == 0;
execute(condition, &pm, &result, &error, settings);
return !error && result == r;
}
bool conditionIsTrue(const Token *condition, const ProgramMemory &programMemory)
bool conditionIsFalse(const Token* condition, ProgramMemory pm, const Settings* settings)
{
if (!condition)
return false;
if (condition->str() == "||") {
return conditionIsTrue(condition->astOperand1(), programMemory) ||
conditionIsTrue(condition->astOperand2(), programMemory);
}
ProgramMemory progmem(programMemory);
bool error = false;
MathLib::bigint result = 0;
execute(condition, &progmem, &result, &error);
return !error && result == 1;
return evaluateCondition("&&", 0, condition, pm, settings);
}
bool conditionIsTrue(const Token* condition, ProgramMemory pm, const Settings* settings)
{
return evaluateCondition("||", 1, condition, pm, settings);
}
static bool frontIs(const std::vector<MathLib::bigint>& v, bool i)
@ -518,7 +516,7 @@ static ValueFlow::Value evaluate(const std::string& op, const ValueFlow::Value&
return result;
}
static ValueFlow::Value execute(const Token* expr, ProgramMemory& pm)
static ValueFlow::Value execute(const Token* expr, ProgramMemory& pm, const Settings* settings = nullptr)
{
ValueFlow::Value unknown = ValueFlow::Value::unknown();
const ValueFlow::Value* value = nullptr;
@ -683,12 +681,32 @@ static ValueFlow::Value execute(const Token* expr, ProgramMemory& pm)
return result;
}
if (Token::Match(expr->previous(), ">|%name% {|(")) {
visitAstNodes(expr->astOperand2(), [&](const Token* child) {
if (child->exprId() > 0 && pm.hasValue(child->exprId())) {
ValueFlow::Value& v = pm.values.at(child->exprId());
if (v.valueType == ValueFlow::Value::ValueType::CONTAINER_SIZE) {
if (isContainerSizeChanged(child, settings))
v = unknown;
} else if (v.valueType != ValueFlow::Value::ValueType::UNINIT) {
if (isVariableChanged(child, v.indirect, settings, true))
v = unknown;
}
}
return ChildrenToVisit::op1_and_op2;
});
}
return unknown;
}
void execute(const Token* expr, ProgramMemory* const programMemory, MathLib::bigint* result, bool* error)
void execute(const Token* expr,
ProgramMemory* const programMemory,
MathLib::bigint* result,
bool* error,
const Settings* settings)
{
ValueFlow::Value v = execute(expr, *programMemory);
ValueFlow::Value v = execute(expr, *programMemory, settings);
if (!v.isIntValue() || v.isImpossible()) {
if (error)
*error = true;

View File

@ -61,21 +61,25 @@ struct ProgramMemoryState {
ProgramMemory get(const Token* tok, const Token* ctx, const ProgramMemory::Map& vars) const;
};
void execute(const Token* expr, ProgramMemory* const programMemory, MathLib::bigint* result, bool* error);
void execute(const Token* expr,
ProgramMemory* const programMemory,
MathLib::bigint* result,
bool* error,
const Settings* settings = nullptr);
/**
* Is condition always false when variable has given value?
* \param condition top ast token in condition
* \param programMemory program memory
*/
bool conditionIsFalse(const Token *condition, const ProgramMemory &programMemory);
bool conditionIsFalse(const Token* condition, ProgramMemory pm, const Settings* settings = nullptr);
/**
* Is condition always true when variable has given value?
* \param condition top ast token in condition
* \param programMemory program memory
*/
bool conditionIsTrue(const Token *condition, const ProgramMemory &programMemory);
bool conditionIsTrue(const Token* condition, ProgramMemory pm, const Settings* settings = nullptr);
/**
* Get program memory by looking backwards from given token.

View File

@ -1939,8 +1939,6 @@ static bool bifurcate(const Token* tok, const std::set<nonneg int>& varids, cons
return false;
}
static bool isContainerSizeChanged(const Token* tok, const Settings* settings = nullptr, int depth = 20);
struct ValueFlowAnalyzer : Analyzer {
const TokenList* tokenlist;
ProgramMemoryState pms;
@ -2387,14 +2385,14 @@ struct ValueFlowAnalyzer : Analyzer {
std::vector<MathLib::bigint> result;
ProgramMemory pm = pms.get(tok, ctx, getProgramState());
if (Token::Match(tok, "&&|%oror%")) {
if (conditionIsTrue(tok, pm))
if (conditionIsTrue(tok, pm, getSettings()))
result.push_back(1);
if (conditionIsFalse(tok, pm))
if (conditionIsFalse(tok, pm, getSettings()))
result.push_back(0);
} else {
MathLib::bigint out = 0;
bool error = false;
execute(tok, &pm, &out, &error);
execute(tok, &pm, &out, &error, getSettings());
if (!error)
result.push_back(out);
}
@ -7012,7 +7010,7 @@ static void valueFlowContainerReverse(Token* tok,
}
}
static bool isContainerSizeChanged(const Token* tok, const Settings* settings, int depth)
bool isContainerSizeChanged(const Token* tok, const Settings* settings, int depth)
{
if (!tok)
return false;

View File

@ -456,6 +456,8 @@ namespace ValueFlow {
std::vector<ValueFlow::Value> isOutOfBounds(const Value& size, const Token* indexTok, bool possible = true);
}
bool isContainerSizeChanged(const Token* tok, const Settings* settings = nullptr, int depth = 20);
struct LifetimeToken {
const Token* token;
bool addressOf;

View File

@ -3828,6 +3828,16 @@ private:
" if (bar(a) && (a + b == 3)) {}\n"
"}\n");
ASSERT_EQUALS("", errout.str());
// #10437
check("void f() {\n"
" Obj* PObj = nullptr;\n"
" bool b = false;\n"
" if (GetObj(PObj) && PObj != nullptr)\n"
" b = true;\n"
" if (b) {}\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void alwaysTrueSymbolic()