Skip to content

Commit bf92303

Browse files
Fix #13092 integerOverflow: distinguish overflow/underflow (danmar#6985)
1 parent ac3c395 commit bf92303

File tree

3 files changed

+22
-8
lines changed

3 files changed

+22
-8
lines changed

lib/checktype.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,35 +199,39 @@ void CheckType::checkIntegerOverflow()
199199
const MathLib::bigint maxvalue = (((MathLib::biguint)1) << (bits - 1)) - 1;
200200

201201
// is there a overflow result value
202+
bool isOverflow = true;
202203
const ValueFlow::Value *value = tok->getValueGE(maxvalue + 1, *mSettings);
203-
if (!value)
204+
if (!value) {
204205
value = tok->getValueLE(-maxvalue - 2, *mSettings);
206+
isOverflow = false;
207+
}
205208
if (!value || !mSettings->isEnabled(value,false))
206209
continue;
207210

208211
// For left shift, it's common practice to shift into the sign bit
209212
if (tok->str() == "<<" && value->intvalue > 0 && value->intvalue < (((MathLib::bigint)1) << bits))
210213
continue;
211214

212-
integerOverflowError(tok, *value);
215+
integerOverflowError(tok, *value, isOverflow);
213216
}
214217
}
215218

216-
void CheckType::integerOverflowError(const Token *tok, const ValueFlow::Value &value)
219+
void CheckType::integerOverflowError(const Token *tok, const ValueFlow::Value &value, bool isOverflow)
217220
{
218221
const std::string expr(tok ? tok->expressionString() : "");
222+
const std::string type = isOverflow ? "overflow" : "underflow";
219223

220224
std::string msg;
221225
if (value.condition)
222226
msg = ValueFlow::eitherTheConditionIsRedundant(value.condition) +
223-
" or there is signed integer overflow for expression '" + expr + "'.";
227+
" or there is signed integer " + type + " for expression '" + expr + "'.";
224228
else
225-
msg = "Signed integer overflow for expression '" + expr + "'.";
229+
msg = "Signed integer " + type + " for expression '" + expr + "'.";
226230

227231
if (value.safe)
228232
msg = "Safe checks: " + msg;
229233

230-
reportError(getErrorPath(tok, &value, "Integer overflow"),
234+
reportError(getErrorPath(tok, &value, "Integer " + type),
231235
value.errorSeverity() ? Severity::error : Severity::warning,
232236
getMessageId(value, "integerOverflow").c_str(),
233237
msg,

lib/checktype.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class CPPCHECKLIB CheckType : public Check {
8181
// Error messages..
8282
void tooBigBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits);
8383
void tooBigSignedBitwiseShiftError(const Token *tok, int lhsbits, const ValueFlow::Value &rhsbits);
84-
void integerOverflowError(const Token *tok, const ValueFlow::Value &value);
84+
void integerOverflowError(const Token *tok, const ValueFlow::Value &value, bool isOverflow = true);
8585
void signConversionError(const Token *tok, const ValueFlow::Value *negativeValue, bool constvalue);
8686
void longCastAssignError(const Token *tok, const ValueType* src = nullptr, const ValueType* tgt = nullptr);
8787
void longCastReturnError(const Token *tok, const ValueType* src = nullptr, const ValueType* tgt = nullptr);

test/testtype.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ class TestType : public TestFixture {
291291
" if (x==123456) {}\n"
292292
" return -123456 * x;\n"
293293
"}",settings);
294-
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'x==123456' is redundant or there is signed integer overflow for expression '-123456*x'.\n", errout_str());
294+
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (warning) Either the condition 'x==123456' is redundant or there is signed integer underflow for expression '-123456*x'.\n", errout_str());
295295

296296
check("int foo(signed int x) {\n"
297297
" if (x==123456) {}\n"
@@ -303,6 +303,16 @@ class TestType : public TestFixture {
303303
" return (i == 31) ? 1 << i : 0;\n"
304304
"}", settings);
305305
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (warning) Shifting signed 32-bit value by 31 bits is undefined behaviour. See condition at line 2.\n", errout_str());
306+
307+
check("void f() {\n" // #13092
308+
" int n = 0;\n"
309+
" for (int i = 0; i < 10; i++) {\n"
310+
" n = n * 47163 - 57412;\n"
311+
" }\n"
312+
"}", settings);
313+
ASSERT_EQUALS("[test.cpp:4]: (error) Signed integer underflow for expression 'n*47163'.\n"
314+
"[test.cpp:4]: (error) Signed integer underflow for expression 'n*47163-57412'.\n",
315+
errout_str());
306316
}
307317

308318
void signConversion() {

0 commit comments

Comments
 (0)