...
If the result of the addition, is greater than the maximum value that the int type can store or less than the minimum value that the int type can store, then the variable temp has a wrong result stored. Although, unlike C\C++ the integer overflow is difficult to exploit by an attacker in Java, because of the memory properties in this platform (e.g. explicit array bound checking; if temp has a negative value as a result of an overflow and we use it as an array index we get an java.lang.ArrayIndexOutOfBoundsException) the results of our operation are wrong and can lead to undefined or incorrect behavior
All the of the following operators can lead to overflow (same as in C\C++):
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 |
| |= | no |
| un + | no |
| || | no |
yes |
| ^= | no |
| yes |
| ?: | no |
...
e.g for the previous example
Compliant Solution (Use long and downcast)
Code Block | ||
---|---|---|
| ||
public int do_operation(int a, int b) throws ArithmeticException { long temp = (long)a+(long)b; if(temp >Integer.MAX_VALUE || temp < Integer.MIN_VALUE) throw ArithmeticException; else //Value within range can perform the addition //Do stuff return (int)temp; } |
Compliant Solution (Bounds Checking)
Another example would be of explicit range checking would be:
Code Block | ||
---|---|---|
| ||
public int do_operation(int a, int b) throws ArithmeticException { int temp; if(a>0 && b>0 && (a >Integer.MAX_VALUE - b) || a<0 && b<0 && (a < Integer.MIN_VALUE -b)) throw ArithmeticException; else temp = a + b;//Value within range can perform the addition //Do stuff return temp; } |
Compliant Solution (Use BigInteger class)
Another compliant approach would be to use the BigInteger class in this example and in the examples of the other operations using a wrapper for test of the overflow:
...
Code Block | ||
---|---|---|
| ||
public int do_operation(int a,int b) { int temp = a - b; //Could result in overflow //perform other processing return temp; } |
Compliant Code Example (Use long)
The appropriate way is to check explicitely the range before doing the subtraction
Code Block | ||
---|---|---|
| ||
int a,b,result; long temp = (long)a-(long)b; if(long < Integer.MIN_VALUE || long > Integer.MAX_VALUE) throw ArithmeticException; else result = (int) temp; |
Compliant Code Example (Use BigInteger class)
A BigInteger class as a test-wrapper could be used
...
Code Block | ||
---|---|---|
| ||
int a,b,result //do stuff result = a*b;//May result in overflow |
Compliant Code Example
Since in this platform the size of type long (64 bits) is twice the size of type int (32 bits) we should perform the multiplication in terms of long and if the product is in the integer range we downcast the result to int
...
Code Block | ||
---|---|---|
| ||
int a,b,result result = a/b; |
Compliant Code Example
Code Block | ||
---|---|---|
| ||
if(a == Integer.MIN_VALUE && b == -1) throw ArithmeticException;//May be Integer.MIN_VALUE again???? else result = a/b;//safe operation |
...
Code Block | ||
---|---|---|
| ||
int temp = -result; |
Compliant Code Example
Code Block | ||
---|---|---|
| ||
if(a == Integer.MIN_VALUE) throw ArithmeticException; else result = -a; |
...
For instance operations on long are operations on 64 bits. For example addition:
Compliant Code Example
Code Block | ||
---|---|---|
| ||
java.math.BigInteger big_long_max = new java.math.BigInteger(String.valueOf(Long.MAX_VALUE)); System.out.println("big_long="+big_long_max); big_long_max = big_long_max.add(java.math.BigInteger.valueOf(1));//same as ++big_long_max System.out.println("big_long="+big_long_max); These print big_long=9223372036854775807 big_long=9223372036854775808//exceeds the maximum range of long, no problem java.math.BigInteger big_long_min = new java.math.BigInteger(String.valueOf(Long.MIN_VALUE)); System.out.println("big_long_min="+big_long_min); big_long_min = big_long_min.subtract(java.math.BigInteger.valueOf(1));//same as --big_long_min System.out.println("big_long_min="+big_long_min);//goes bellow minimum range of long, no problem These print: big_long_min=-9223372036854775808 big_long_min=-9223372036854775809 if(big_long < Long.MAX_VALUE && big_long > Long.MIN_VALUE)//value within range can go to the primitive type long value = big_log.longValue();//get primitive type else //Perform error handling. We can not downcast since the value can not be represented as a long |
...