diff --git a/lib/infer.cpp b/lib/infer.cpp index cad0761f68b..f9bd368af85 100644 --- a/lib/infer.cpp +++ b/lib/infer.cpp @@ -127,8 +127,12 @@ namespace { Interval result; const ValueFlow::Value* minValue = getCompareValue(values, predicate, std::less{}); if (minValue) { - if (minValue->isImpossible() && minValue->bound == ValueFlow::Value::Bound::Upper) - result.setMinValue(minValue->intvalue + 1, minValue); + if (minValue->isImpossible() && minValue->bound == ValueFlow::Value::Bound::Upper) { + if (std::numeric_limits::max() == minValue->intvalue) + result.setMinValue(minValue->intvalue, minValue); + else + result.setMinValue(minValue->intvalue + 1, minValue); + } if (minValue->isPossible() && minValue->bound == ValueFlow::Value::Bound::Lower) result.setMinValue(minValue->intvalue, minValue); if (!minValue->isImpossible() && (minValue->bound == ValueFlow::Value::Bound::Point || minValue->isKnown()) && @@ -137,8 +141,12 @@ namespace { } const ValueFlow::Value* maxValue = getCompareValue(values, predicate, std::greater{}); if (maxValue) { - if (maxValue->isImpossible() && maxValue->bound == ValueFlow::Value::Bound::Lower) - result.setMaxValue(maxValue->intvalue - 1, maxValue); + if (maxValue->isImpossible() && maxValue->bound == ValueFlow::Value::Bound::Lower) { + if (std::numeric_limits::min() == maxValue->intvalue) + result.setMaxValue(minValue->intvalue, maxValue); + else + result.setMaxValue(maxValue->intvalue - 1, maxValue); + } if (maxValue->isPossible() && maxValue->bound == ValueFlow::Value::Bound::Upper) result.setMaxValue(maxValue->intvalue, maxValue); assert(!maxValue->isKnown()); @@ -312,14 +320,20 @@ std::vector infer(const ValuePtr& model, result.push_back(std::move(value)); } else { if (!diff.minvalue.empty()) { - ValueFlow::Value value(diff.minvalue.front() - 1); + int adder(0); + if (std::numeric_limits::min() < diff.minvalue.front()) + adder = -1; + ValueFlow::Value value(diff.minvalue.front() + adder); value.setImpossible(); value.bound = ValueFlow::Value::Bound::Upper; addToErrorPath(value, diff.minRef); result.push_back(std::move(value)); } if (!diff.maxvalue.empty()) { - ValueFlow::Value value(diff.maxvalue.front() + 1); + int adder(0); + if (std::numeric_limits::max() > diff.maxvalue.front()) + adder = 1; + ValueFlow::Value value(diff.maxvalue.front() + adder); value.setImpossible(); value.bound = ValueFlow::Value::Bound::Lower; addToErrorPath(value, diff.maxRef); diff --git a/lib/token.cpp b/lib/token.cpp index 98f79b4bb1d..ac836f53a04 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -2015,7 +2015,11 @@ static bool isAdjacent(const ValueFlow::Value& x, const ValueFlow::Value& y) return true; if (x.valueType == ValueFlow::Value::ValueType::FLOAT) return false; - return std::abs(x.intvalue - y.intvalue) == 1; + + // original abs() is not safe against overflows: + // return std::abs(x.intvalue - y.intvalue) == 1; + return (y.intvalue != std::numeric_limits::max() && x.intvalue == y.intvalue + 1) || + (y.intvalue != std::numeric_limits::min() && x.intvalue == y.intvalue - 1); } static bool removePointValue(std::list& values, std::list::iterator& x) diff --git a/lib/vf_common.cpp b/lib/vf_common.cpp index 0498a7e303d..d2cf1bffed0 100644 --- a/lib/vf_common.cpp +++ b/lib/vf_common.cpp @@ -38,6 +38,7 @@ #include #include #include +#include namespace ValueFlow { @@ -101,6 +102,9 @@ namespace ValueFlow if (value_size == 0) return value; + // sizeof(long long) = 8 + value_size = std::min(sizeof(MathLib::bigint), value_size); + const MathLib::biguint unsignedMaxValue = std::numeric_limits::max() >> ((sizeof(unsignedMaxValue) - value_size) * 8); const MathLib::biguint signBit = 1ULL << (value_size * 8 - 1); value &= unsignedMaxValue;