Wiki Markup |
---|
The following excerpt is fromAccording to Sun's Secure Coding Guidelines document \[[SCG 07|AA. Java References#SCG 07]\]: |
...
Wiki Markup |
---|
The following excerpt is from the Java Language Specification \[[JLS 03|AA. Java References#JLS 03]\], section 4.2.2 Integer Operations: |
...
If the result of the addition is greater than the maximum value or less than the minimum value that the int
type can storerepresent, then the variable temp
will contain an erroneous result. Unlike C and C++ integer overflows are harder to exploit in Java. For example, if temp
has a negative value as a result of an overflow and is used as an array index, java.lang.ArrayIndexOutOfBoundsException
) results in Java, whereas this is a more pernicious issue in C and C++ wherein because memory regions outside the array bounds can be maliciously altered. In Java, wrapped values typically result in incorrect computations and unanticipated outcomes.
...
Wiki Markup |
---|
According to the Java Tutorials \[[Tutorials 08|AA. Java References#Tutorials 08]\], Primitive Data Types: |
...
The
int
data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive).
...
The
long
data type is a 64-bit signed two's complement integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive). Use this data type when you need a range of values wider than those provided byint
.
Since a variable of the long
type is guaranteed to hold the result of an addition, subtraction or multiplication of values of type int
, the result can be assigned to such a variable of type long
, and if the result is in the integer range, we can simply downcast it to a value of type int
.
Compliant Solution (Use long
and Downcast)
This compliant solution uses a variable of type long
to store the result of the addition and proceeds to range check the its value. If the value cannot be represented as in a value variable of type int
, it throws an ArithmeticException
. Otherwise, it downcasts the result to a value of type int
.
Code Block | ||
---|---|---|
| ||
public int do_operation(int a, int b) throws ArithmeticException { long temp = (long)a + (long)b; if(temp > >IntegerInteger.MAX_VALUE || temp < Integer.MIN_VALUE) { throw new ArithmeticException("Not in range"); } return (int)temp; // Value within range can perform the addition } |
Compliant Solution (Bounds Checking)
This compliant solution uses range checking checks the operand values to ensure that the result will does not overflow.
Code Block | ||
---|---|---|
| ||
public int do_operation(int a, int b) throws ArithmeticException { if( b>0 ? a > Integer.MAX_VALUE - b : a < Integer.MIN_VALUE - b ) { throw new ArithmeticException("Not in range"); } return a + b; //Value within range so addition can performbe the additionperformed } |
Compliant Solution (Use BigInteger Class)
...
Code Block | ||
---|---|---|
| ||
public boolean overflow(long a, long b) { BigInteger ba = new java.math.BigInteger(String.valueOf(a)); BigInteger bb = new java.math.BigInteger(String.valueOf(b)); BigInteger br = ba.add(bb); return (br.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) == 1 || br.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) == -1); } public long do_operation(long a, long b) throws ArithmeticException { if(overflow(a,b)) { throw new ArithmeticException("Not in range"); } // Within range; safely perform the addition return a + b; } |
With use of the BigInteger
class, integer overflows are definitely eliminated. However, due to increased performance costs, it should be used only when other methods are not appropriate.
...
Care must be taken while performing the subtraction operation as well since because overflows (or underflows) are still possible.
Noncompliant Code Example
...
Code Block | ||
---|---|---|
| ||
public int do_operation(int a, int b) throws ArithmeticException { if(b > b>00 ? a < Integer.MIN_VALUE + b : a > Integer.MAX_VALUE + b ) { throw new ArithmeticException("Not in range"); } return a - b; //Value within range can perform the addition } |
Compliant
...
Solution (Use BigInteger Class)
The BigInteger
class can be used as a overflow-test - wrapper as shown in this compliant solution.
...
Code Block | ||
---|---|---|
| ||
int a, b, result //do stuff result = a * b; // May result in overflow |
Compliant Solution
Since Because the size of the type long
(64 bits) is twice the size of the type int
(32 bits), the multiplication should be performed using a variable of type long
. If the product is in the range of the int
type, it can be safely downcast to a value of type int
.
Code Block | ||
---|---|---|
| ||
int a, b, result; long temp = (long) a * (long)b; if(temp > Integer.MAX_VALUE || temp < Integer.MIN_VALUE) { throw new ArithmeticException("Not in range"); // Overflow } result = (int) temp; // Value within range, safe to downcast |
...
Although Java throws a java.lang.ArithmeticException
for division by zero, the same issue as with C/C++ manifests, while dividing the Integer.MIN_VALUE
by -1. It produces Integer.MIN_VALUE
unexpectedly (since as the result is -(Integer.MIN_VALUE) = Integer.MAX_VALUE + 1
)).
...
This compliant solution handles the the special case of Integer.MIN_VALUE
and -1
being used as the dividend and divisor, respectively.
...
- The sign of the remainder is always the same as that of the dividend. For example,
-3
%-2
will result results in the value-1
. As a result its This behavior can sometimes be deceptive.
...
A related pitfall is the use of the Math.abs()
method that takes a parameter of type int
and returns its absolute value. Because of the asymmetry between the representation of negative and positive integer values (Integer.MAX_VALUE
is 2147483647 and Integer.MIN_VALUE
is -2147483648, which means there is one more negative integer than positive integers), there is no equivalent positive value (+2147483648) for Integer.MIN_VALUE
.
Shifting
The shift operation in Java is quite different from C/C++,
...
Noncompliant Code Example
Wiki Markup |
---|
InThis noncompliant thiscode example, the programmerattempts wishes to shift the value {{i}} of type {{int}} until, after 32 iterations, the value becomes 0. Unfortunately, this loop never terminates asbecause an attempt to shift a value of type {{int}} by 32 bits results in the original value rather than the value 0. \[[Bloch 05|AA. Java References#Bloch 05]\] |
...