Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

See the following example:

Noncompliant Code Example

 In we have the following simple method the result could overflow

...

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

 

un -

yes

 

?:

no


Addition

Addition (and all operations) in Java are performed in signed numbers as Java does not support unsigned numbers

Noncompliant Code Example

In this example the addition could result in overflow

Code Block
bgColor#FFcccc
public int do_operation(int a,int b)
{
   int temp = a + b;
//Could result in overflow
//do other processing
   return temp;
}



Compliant Solution (Bounds Checking)


A solution would be to explicitly check the range of each arithmetic operation and throw an ArithmeticException on overflow, otherwise downcast the value to an integer. For arithmetical operations on  really big numbers one should always use the BigInteger Class

...

e.g for the previous example

Compliant Solution (Use long and downcast)


 

Code Block
bgColor#ccccff
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
bgColor#ccccff
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:

...


By using the BigInteger class there is no chance to overflow (see section on BigInteger class) but the performance is degraded so it should be used only on really large operations












Subtraction


Care must be taken in subtraction operations as well as these can overflow as well.

Noncompliant Code Example


Code Block
bgColor#FFcccc
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
bgColor#ccccff
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
bgColor#ccccff
public bool underflow(int a, int b)
{
    java.math.BigInteger ba = new java.math.BigInteger(String.valueOf(a));
    java.math.BigInteger bb = new java.math.BigInteger(String.valueOf(b));
    java.math.BigInteger br = ba.subtract(bb);
    if(br.compareTo(java.math.BigInteger.valueOf(Integer.MAX_VALUE)) == 1
              || br.compareTo(java.math.BigInteger.valueOf(Integer.MIN_VALUE))== -1)
        return true;//We have underflow
    //Can proceed
   return false
}

public int do_operation(int a, int b) throws ArithmeticException
{
      if(undeflow(a,b))
         throw ArithmeticException;
      else //we are within range safely perform the addition
}













Multiplication


This noncompliant code example, can result in a signed integer overflow during the multiplication of the signed operands a and b. If this behaviour is unanticipated, the resulting value may lead to undefined behaviour

Noncompliant Code Example


 

Code Block
bgColor#FFcccc
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
bgColor#ccccff
int a,b,result;
long temp = (long) a\* (long)b;
if(temp > Integer.MAX_VALUE || temp < Integer.MIN_VALUE)
throw ArithmeticException;//overflow
else
result = (int) temp;//Value within range, safe to downcast



Division


Although Java throws a java.lang.ArithmeticException: / by zero exception for division by zero, there is the same issue as in C\C++ when dividing the Integer.MIN_VALUE with -1. It produces Integer.MIN_VALUE unexpectedly

...

A non-compliant example is:

Noncompliant Code Example


 

Code Block
bgColor#FFcccc
int a,b,result
result = a/b;












Compliant Code Example


 

Code Block
bgColor#ccccff
if(a == Integer.MIN_VALUE && b == -1)
throw ArithmeticException;//May be Integer.MIN_VALUE again????
else
result = a/b;//safe operation



 

Modulo


Modulo operation is safer in Java than C/C++

...

-if the right-hand operand is zero then the integer remainder operator %, will throw an ArithmeticException


 

Unary Negation


If we negate Integer.MIN_VALUE we get Integer.MIN_VALUE. So we explicitely check the range

Noncompliant Code Example


Code Block
bgColor#FFcccc
int temp = -result;








Compliant Code Example


Code Block
bgColor#ccccff
if(a == Integer.MIN_VALUE)
throw ArithmeticException;
else
result = -a;










SHIFTING


The shift in java is quite different than in C\C++.

...

Code Block
bgColor#ccccff
public int do_shift(int shift_value){ 
   if(shift_value > 31 or shift_value <0)
      throw ArithmeticException;
   else
      int val = 2 << shift_value;
}










Unsigned Right shifting >>>


It is identical to the right-shift operator if the shifted value is positive. If it is negative the sign value can change because the left-operand high-order bit is not retained and the sign value can change; Excerpt from JLS:
"if n is negative, the result is equal to that of the expression (n>>s)(2<<~s) if the type of the left-hand operand is int, and to the result of the expression (n>>s)(2L<<~s) if the type of the left-hand operand is long. The added term (2<<~s) or (2L<<~s) cancels out the propagated sign bit. (Note that, because of the implicit masking of the right-hand operand of a shift operator, ~s as a shift distance is equivalent to 31-s when shifting an int value and to 63-s when shifting a longvalue.)"

 For example: -32 >>> 2 = (-32 >> 2 ) + ( 2 << ~2 ) = 1073741816

Operations Requiring Really Long Numbers


For these operations the BigInteger class should be used. According to SUN BigInteger Class:

...

For instance operations on long are operations on 64 bits. For example addition:

Compliant Code Example


 

Code Block
bgColor#ccccff
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

We can always go back to the primitive types if the BigInteger of course can be represented by the type
In the example if big_long is within long range (big_long < Long.MAX_VALUE && big_long > Long.MIN_VALUE) we can use the BigInteger method longValue() to get the long value and assign it to a variable of type long



Risk Assesment

Integer overflows are among the most dangerous defects in software since it leads to exploitation, undefined and erroneous behavior

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

INT34-J

high

likely

high

P6

L2


Other Languages

This rule appears as in the C++ Secure Coding standard as: INT32-CPP. Ensure that operations on signed integers do not result in overflow

This rule also appears in the C Secure Coding Standard as: INT32-C. Ensure that operations on signed integers do not result in overflow

References


Secure Coding Guidelines for the Java Programming Language: Secure (Paragraph on comparison C++/Java)

...