...
The following code example shows the necessary pre-condition 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.
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)
throws ArithmeticException {
if (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);
}
|
...
Either operation in this noncompliant code example could result in an overflow. When overflow occurs, the result will be incorrect.
Code Block | ||
---|---|---|
| ||
public static int multAccum(int oldAcc, int newVal, int scale) {
// May result in overflow
return oldAcc + (newVal * scale);
}
|
...
This compliant solution uses the safeAdd()
and safeMultiply()
methods defined in the Precondition Testing section to perform secure integral operations or throw ArithmeticException
on overflow.
Code Block | ||
---|---|---|
| ||
public static int multAccum(int oldAcc, int newVal, int scale)
throws ArithmeticException {
return safeAdd(oldAcc, safeMultiply(newVal, scale));
}
|
...
This compliant solution shows the implementation of a method for checking whether a value of type long
falls within the representable range of an int
using the upcasting technique. The implementations of range checks for the smaller primitive integer types are similar.
Code Block | ||
---|---|---|
| ||
public static long intRangeCheck(long value)
throws ArithmeticException {
if ((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 down-cast
}
|
...
This compliant solution uses the BigInteger
technique to detect overflow.
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 (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
}
|
...
This noncompliant code example uses an AtomicInteger
, which is part of the concurrency utilities. The concurrency utilities lack integer overflow checks.
Code Block | ||
---|---|---|
| ||
class InventoryManager {
private final AtomicInteger itemsInInventory = new AtomicInteger(100);
//...
public final void nextItem() {
itemsInInventory.getAndIncrement();
}
}
|
...
- The number and order of accesses to
itemsInInventory
remain unchanged from the noncompliant code example. - All operations on the value of
itemsInInventory
are performed on a temporary local copy of its value. - The overflow check in this example is performed in inline code rather than encapsulated in a method call. This is an acceptable alternative implementation. The choice of method call versus inline code should be made according to your organization's standards and needs.
Code Block | ||
---|---|---|
| ||
class InventoryManager {
private final AtomicInteger itemsInInventory =
new AtomicInteger(100);
public final void nextItem() {
while (true) {
int old = itemsInInventory.get();
if (old == Integer.MAX_VALUE) {
throw new ArithmeticException("Integer overflow");
}
int next = old + 1; // Increment
if (itemsInInventory.compareAndSet(old, next)) {
break;
}
} // end while
} // end nextItem()
}
|
...
INT32-C. Ensure that operations on signed integers do not result in overflow | |
INT32-CPP. Ensure that operations on signed integers do not result in overflow | |
Wrap-around Error [XYY] | |
CWE-682. Incorrect calculation | |
| CWE-190. Integer overflow or wraparound |
| CWE-191. Integer underflow (wrap or wraparound) |
Android Implementation Details
Mezzofanti for Android contained an integer overflow which prevented the use of a big SD card. Mezzofanti contained an expression:
(int) StatFs.getAvailableBlocks() * (int) StatFs.getBlockSize()
to calculate the available memory in an SD card, which could result in a negative value when the available memory is bigger than Integer.MAX_VALUE
.
Note these methods are deprecated in API level 18 and replaced by getAvailableBlocksLong()
and getBlockSizeLong()
.
Bibliography
[API 2006] | Class |
Puzzle 27. Shifty i's | |
[JLS 2005] | |
| |
Chapter 5, Integers | |
Primitive Data Types |
03. Numeric Types and Operations (NUM) 03. Numeric Types and Operations (NUM)