How to prevent integer overflow in Java code?
Solution 1
It is a difficult problem from an engineering perspective.
The Secure Coding site recommends:
- use of preconditions; i.e. range-check the inputs so that overflow is impossible,
- doing each individual arithmetic operation using the next larger primitive integer type and explicitly checking for overflow, or
- using BigInteger.
This Dr Dobbs article suggests creating a library of primitive arithmetic methods that do each primitive operation with an explicit overflow check. (You could view this as an implementation of bullet point #2 above.) But the authors go further by suggesting that you use bytecode rewriting to replace arithmetic bytecodes with calls to the equivalent methods which incorporate overflow checks.
Unfortunately, there is no way to enable overflow checking natively in Java. (But the same applies in lots of other languages; e.g. C, C++ ... )
Solution 2
One way to check for an overflow is to have the operands promoted to a larger type (of double the original operand bit length) then perform the operation, and then see if the resulting value is too large for the original type, e.g.
int sum(int a, int b) {
long r = (long)a + b;
if (r >>> 32 != 0) { // no sign extension
throw new MyOverflowException(a, b);
}
return (int)r;
}
If your original type is a long
, you'd have to use BigInteger
as that larger type.
Solution 3
Sum: Check whether b is larger than the difference of the maximum value you can store in int minus the value of a. If a and/or b can be negative, you must (i) be careful not to get an overflow already for the difference check and (ii) perform a similar check for the minimum.
Product: Thats more difficult. I would split the integers into two half-length integers (i.e. if int is 32 bit, split it into two 16 bit numbers using bit-masking and shifting). Then do the multiplication, and then look whether the result fits into 32 bit.
Everything under the condition that you do not want to simply take long
for the temporary result.
Solution 4
Suppose both a and b are positive or negative, and if the sign of a + b is not equal with the sign of a and b, then overflow happens. You can use this rule to judge whether overflow happens and throw an exception. When you catch this expcetion, you can deal it according to the method metioned in previous answers. Another method is to doing operation using largest range type which will not overflow. You can use long for the operation between Integers.
Comments
-
Michael almost 4 years
Possible Duplicate:
How can I check if multiplying two numbers in Java will cause an overflow?Suppose I have a Java class method, which uses
*
and+
operations.int foo(int a, int b) { ... // some calculations with + and * }
How to make sure that no overflow occurs in
foo
?I guess I can either use
BigDecimal
or replace all + and * with "wrappers" like:int sum(int a, int b) { int c = a + b; if (a > 0 && b > 0 && c < 0) throw new MyOverfowException(a, b) return c; } int prod(int a, int b) { int c = a * b; if (a > 0 && b > 0 && c < 0) throw new MyOverfowException(a, b) return c; }
Are there better ways to make sure that no
int
overflow occurs in a Java method ? -
Alnitak almost 12 yearsthe second of those is what my answer does
-
Rich over 10 years"It is a difficult problem from an engineering perspective." -- It's not that difficult: just generate machine code to check the overflow register flag after every operation. That's what the C# "checked" block does. The issue is that Java doesn't offer that as an option, not because it is beyond the wit of man.
-
Stephen C over 10 years@Rich - it is difficult if you are not in a position to modify the Java compiler. Most people aren't!
-
Rich over 10 yearslol, good point :-) It's frustrating that this wasn't included in the Java compiler. There isn't a nice easy answer (which is also correct) on this question or it's duplicate :-(
-
Rich over 10 years
-
yitzih almost 8 yearsI know this answer is old, but this solution isn't guaranteed to work since the larger type itself can overflow and end up in a range that appears normal for the smaller type.
-
Alnitak almost 8 years@yitzih you're wrong - the addition of two (positive) integers cannot exceed a value any more than 1 bit longer than the longest operand. There's no way given the constraints of the question to end up with a "larger type itself overflow"
-
Alnitak almost 8 years@yitzihI I forgot that multiplication is also involved, but there too, the product of two 31 bit positive integers cannot exceed 62 bits.
-
yitzih almost 8 yearsthat's a fair point. My mistake, thank you for clarifying.