Skip to content

Commit da380ea

Browse files
Fix #11591 Truncate variable after pre/post increment operator (#6331)
1 parent 94f28a2 commit da380ea

2 files changed

Lines changed: 40 additions & 8 deletions

File tree

lib/valueflow.cpp

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,17 @@ static ValueFlow::Value truncateImplicitConversion(Token* parent, const ValueFlo
604604
return v;
605605
}
606606

607+
static long long truncateIntValue(long long value, size_t value_size, const ValueType::Sign dst_sign)
608+
{
609+
const MathLib::biguint unsignedMaxValue = (1ULL << (value_size * 8)) - 1ULL;
610+
const MathLib::biguint signBit = 1ULL << (value_size * 8 - 1);
611+
value &= unsignedMaxValue;
612+
if (dst_sign == ValueType::Sign::SIGNED && (value & signBit))
613+
value |= ~unsignedMaxValue;
614+
615+
return value;
616+
}
617+
607618
/** set ValueFlow value and perform calculations if possible */
608619
static void setTokenValue(Token* tok,
609620
ValueFlow::Value value,
@@ -2817,7 +2828,16 @@ struct ValueFlowAnalyzer : Analyzer {
28172828
if (d == Direction::Reverse)
28182829
inc = !inc;
28192830
value->intvalue += (inc ? 1 : -1);
2820-
value->errorPath.emplace_back(tok, tok->str() + " is " + opName + "', new value is " + value->infoString());
2831+
2832+
/* Truncate value */
2833+
const ValueType *dst = tok->valueType();
2834+
if (dst) {
2835+
const size_t sz = ValueFlow::getSizeOf(*dst, settings);
2836+
if (sz > 0 && sz < 8)
2837+
value->intvalue = truncateIntValue(value->intvalue, sz, dst->sign);
2838+
2839+
value->errorPath.emplace_back(tok, tok->str() + " is " + opName + "', new value is " + value->infoString());
2840+
}
28212841
}
28222842
}
28232843

@@ -6028,13 +6048,8 @@ static std::list<ValueFlow::Value> truncateValues(std::list<ValueFlow::Value> va
60286048
value.valueType = ValueFlow::Value::ValueType::INT;
60296049
}
60306050

6031-
if (value.isIntValue() && sz > 0 && sz < 8) {
6032-
const MathLib::biguint unsignedMaxValue = (1ULL << (sz * 8)) - 1ULL;
6033-
const MathLib::biguint signBit = 1ULL << (sz * 8 - 1);
6034-
value.intvalue &= unsignedMaxValue;
6035-
if (dst->sign == ValueType::Sign::SIGNED && (value.intvalue & signBit))
6036-
value.intvalue |= ~unsignedMaxValue;
6037-
}
6051+
if (value.isIntValue() && sz > 0 && sz < 8)
6052+
value.intvalue = truncateIntValue(value.intvalue, sz, dst->sign);
60386053
}
60396054
return values;
60406055
}

test/testvalueflow.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class TestValueFlow : public TestFixture {
150150
TEST_CASE(valueFlowIdempotent);
151151
TEST_CASE(valueFlowUnsigned);
152152
TEST_CASE(valueFlowMod);
153+
TEST_CASE(valueFlowInc);
153154
TEST_CASE(valueFlowNotNull);
154155
TEST_CASE(valueFlowSymbolic);
155156
TEST_CASE(valueFlowSymbolicIdentity);
@@ -7879,6 +7880,22 @@ class TestValueFlow : public TestFixture {
78797880
ASSERT_EQUALS(false, testValueOfXImpossible(code, 3U, 1));
78807881
}
78817882

7883+
void valueFlowInc() {
7884+
const char *code;
7885+
std::list<ValueFlow::Value> values;
7886+
7887+
// #11591
7888+
code = "int f() {\n"
7889+
" const int a[1] = {};\n"
7890+
" unsigned char i = 255;\n"
7891+
" ++i;\n"
7892+
" return a[i];\n"
7893+
"}\n";
7894+
values = tokenValues(code, "i ]");
7895+
ASSERT_EQUALS(1U, values.size());
7896+
ASSERT_EQUALS(0LLU, values.back().intvalue);
7897+
}
7898+
78827899
void valueFlowNotNull()
78837900
{
78847901
const char* code;

0 commit comments

Comments
 (0)