...
The integral types in Java, representation, and inclusive ranges are shown in the following table taken from the JLS, §4.2.1, "Integral Types and Values" [JLS 2015]:
Type | Representation | Inclusive Range |
---|---|---|
| 8-bit signed two's-complement | −128 to 127 |
| 16-bit signed two's-complement | −32,768 to 32,767 |
| 32-bit signed two's-complement | −2,147,483,648 to 2,147,483,647 |
| 64-bit signed two's-complement | −9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
| 16-bit unsigned integers representing UTF-16 code units |
|
The following table shows the integer overflow behavior of the integral operators.
Operator | Overflow |
---|
Operator | Overflow |
---|
Operator | Overflow |
---|
Operator | Overflow | |
---|---|---|
| Yes |
| Yes |
| No |
| No | ||
| Yes |
| Yes |
| No |
| No | |
| Yes |
| Yes |
| No |
| No | ||
| Yes |
| No |
| No |
| No | ||
| No |
| No |
| No |
| No | ||
| Yes |
| No |
| No |
| No | ||
| Yes |
| No |
| No | ||
| No |
| No |
Unary | No | ||
| Yes |
| No |
Unary | Yes |
Because the ranges of Java types are not symmetric (the negation of each minimum value is one more than each maximum value), even operations such as unary negation can overflow if applied to a minimum value. Because the java.lang.math.abs()
method returns the absolute value of any number, it can also overflow if given the minimum int
or long
as an argument.
...
The following code example shows the necessary precondition checks required for each arithmetic operation on arguments of type int
. The checks for the other integral types are analogous. These methods throw an exception when an integer overflow would otherwise occur; any other conforming error handling is also acceptable. Since ArithmeticException
inherits from RuntimeException
, we do not need to declare it in a throws
clause.
Code Block | ||
---|---|---|
| ||
Code Block | ||
| ||
static final int safeAdd(int left, int right) throws ArithmeticException { if (right > 0 ? left > Integer.MAX_VALUE - right : left < Integer.MIN_VALUE - right) { throw new ArithmeticException("Integer overflow"); } return left + right; } static final int safeSubtract(int left, int right) throws ArithmeticException { if (right > 0 ? left < Integer.MIN_VALUE + right : left > Integer.MAX_VALUE + right) { throw new ArithmeticException("Integer overflow"); } return left - right; } static final int safeMultiply(int left, int right) { if throws ArithmeticException { if (right (right > 0 ? left > Integer.MAX_VALUE/right || left < Integer.MIN_VALUE/right : (right < -1 ? left > Integer.MIN_VALUE/right || left < Integer.MAX_VALUE/right : right == -1 && left == Integer.MIN_VALUE) ) { throw new ArithmeticException("Integer overflow"); } return left * right; } static final int safeDivide(int left, int right) throws ArithmeticException { if ((left == Integer.MIN_VALUE) && (right == -1)) { throw new ArithmeticException("Integer overflow"); } return left / right; } static final int safeNegate(int a) throws ArithmeticException { if (a == Integer.MIN_VALUE) { throw new ArithmeticException("Integer overflow"); } return -a; } static final int safeAbs(int a) throws ArithmeticException { if (a == Integer.MIN_VALUE) { throw new ArithmeticException("Integer overflow"); } return Math.abs(a); } |
...
Code Block | ||
---|---|---|
| ||
public static int multAccum(int oldAcc, int newVal, int scale) { return throws ArithmeticException { return safeAdd(oldAcc, safeMultiply(safeAdd(oldAcc, safeMultiply(newVal, scale)); } |
Compliant Solution (Java 8, Math.*Exact()
)
...
Code Block | ||
---|---|---|
| ||
public static int multAccum(int oldAcc, int newVal, int scale) throws ArithmeticException { return Math.addExact(oldAcc, Math.multiplyExact(newVal, scale)); } |
...
Code Block | ||
---|---|---|
| ||
public static long intRangeCheck(long value) { if ((value < throws ArithmeticException { if ((value < Integer.MIN_VALUE) Integer.MIN_VALUE) || (value > Integer.MAX_VALUE)) { throw new ArithmeticException("Integer overflow"); } return value; } public static int multAccum(int oldAcc, int newVal, int scale) throws ArithmeticException { final long res = intRangeCheck( ((long) oldAcc) + intRangeCheck((long) newVal * (long) scale) ); return (int) res; // Safe downcast } |
...
Code Block | ||
---|---|---|
| ||
private static final BigInteger bigMaxInt = BigInteger.valueOf(Integer.MAX_VALUE); private static final BigInteger bigMinInt = BigInteger.valueOf(Integer.MIN_VALUE); public static BigInteger intRangeCheck(BigInteger val) { throws ArithmeticException { if (valif (val.compareTo(bigMaxInt) == 1 || val.compareTo(bigMinInt) == -1) { throw new ArithmeticException("Integer overflow"); } return val; } public static int multAccum(int oldAcc, int newVal, int scale) throws ArithmeticException { BigInteger product = BigInteger.valueOf(newVal).multiply(BigInteger.valueOf(scale)); BigInteger res = intRangeCheck(BigInteger.valueOf(oldAcc).add(product)); return res.intValue(); // Safe conversion } |
...
Failure to perform appropriate range checking can lead to integer overflows, which can cause unexpected program control flow or unanticipated program behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
NUM00-J | Medium | Unlikely | Medium | P4 | L3 |
Automated Detection
Automated detection of integer operations that can potentially overflow is straightforward. Automatic determination of which potential overflows are true errors and which are intended by the programmer is infeasible. Heuristic warnings might be helpful.
Tool |
---|
BAD_SHIFT
OVERFLOW_BEFORE_WIDEN
Version | Checker | Description | |||||||
---|---|---|---|---|---|---|---|---|---|
CodeSonar |
| JAVA.MATH.ABSRAND | Abs on random (Java) | ||||||
Coverity | 7.5 | BAD_SHIFT | Implemented | ||||||
Parasoft Jtest |
| CERT.NUM00.ICO CERT.NUM00.BSA CERT.NUM00.CACO | Avoid calculations which result in overflow or NaN Do not use an integer outside the range of [0, 31] as the amount of a shift Avoid using compound assignment operators in cases which may cause overflow | ||||||
PVS-Studio |
| V5308, V6117 |
Related Guidelines
INT32-C. Ensure that operations on signed integers do not result in overflow | |
Wrap-around Error [XYY] | |
CWE-682, Incorrect Calculation |
Android Implementation Details
...
to calculate the available memory in an SD card, which could result in a negative value when the available memory is larger than Integer.MAX_VALUE
. Note that these methods are deprecated in API level 18 and replaced by getAvailableBlocksLong()
and getBlockSizeLong()
.
Bibliography
[API 2006] | Class |
Puzzle 27, "Shifty i's" | |
[Bloch 2008] | Item 12, "Minimize the Accessibility of Classes and Members" |
[JLS 2015] | §4.2.1, "Integral Types and Values" |
Chapter 5, "Integers" | |
[Seacord 2015] |
...
...