diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 014a8c619..bdda39a00 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3564,6 +3564,30 @@ static void valueFlowForwardAssign(Token * const tok, valueFlowForward(const_cast(nextExpression), endOfVarScope, var, var->declarationId(), values, constValue, false, tokenlist, errorLogger, settings); } +static std::list truncateValues(std::list values, const ValueType *valueType, const Settings *settings) +{ + if (!valueType || !valueType->isIntegral()) + return values; + + const size_t sz = getSizeOf(*valueType, settings); + + for (ValueFlow::Value &value : values) { + if (value.isFloatValue()) { + value.intvalue = value.floatValue; + value.valueType = ValueFlow::Value::INT; + } + + if (value.isIntValue() && sz > 0 && sz < 8) { + const MathLib::biguint unsignedMaxValue = (1ULL << (sz * 8)) - 1ULL; + const MathLib::biguint signBit = 1ULL << (sz * 8 - 1); + value.intvalue &= unsignedMaxValue; + if (valueType->sign == ValueType::Sign::SIGNED && (value.intvalue & signBit)) + value.intvalue |= ~unsignedMaxValue; + } + } + return values; +} + static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings) { for (const Scope * scope : symboldatabase->functionScopes) { @@ -3593,7 +3617,7 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat if (!tok->astOperand2() || tok->astOperand2()->values().empty()) continue; - std::list values = tok->astOperand2()->values(); + std::list values = truncateValues(tok->astOperand2()->values(), tok->astOperand1()->valueType(), settings); const bool constValue = tok->astOperand2()->isNumber(); const bool init = var->nameToken() == tok->astOperand1(); valueFlowForwardAssign(const_cast(tok->astOperand2()), var, values, constValue, init, tokenlist, errorLogger, settings); diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 26820e14b..9d33fef7e 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -1443,6 +1443,25 @@ private: "}"; ASSERT_EQUALS(false, testValueOfX(code, 4U, 0)); + // truncation + code = "int f() {\n" + " int x = 1.5;\n" + " return x;\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 1)); + + code = "int f() {\n" + " unsigned char x = 0x123;\n" + " return x;\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 0x23)); + + code = "int f() {\n" + " signed char x = 0xfe;\n" + " return x;\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, -2)); + // function code = "void f() {\n" " char *x = 0;\n"