How to prevent integer overflow in Java code?

35,883

Solution 1

It is a difficult problem from an engineering perspective.

The Secure Coding site recommends:

  • use of preconditions; i.e. range-check the inputs so that overflow is impossible,
  • doing each individual arithmetic operation using the next larger primitive integer type and explicitly checking for overflow, or
  • using BigInteger.

This Dr Dobbs article suggests creating a library of primitive arithmetic methods that do each primitive operation with an explicit overflow check. (You could view this as an implementation of bullet point #2 above.) But the authors go further by suggesting that you use bytecode rewriting to replace arithmetic bytecodes with calls to the equivalent methods which incorporate overflow checks.

Unfortunately, there is no way to enable overflow checking natively in Java. (But the same applies in lots of other languages; e.g. C, C++ ... )

Solution 2

One way to check for an overflow is to have the operands promoted to a larger type (of double the original operand bit length) then perform the operation, and then see if the resulting value is too large for the original type, e.g.

int sum(int a, int b) {
    long r = (long)a + b;
    if (r >>> 32 != 0) {    // no sign extension
        throw new MyOverflowException(a, b);
    }
    return (int)r;
}

If your original type is a long, you'd have to use BigInteger as that larger type.

Solution 3

Sum: Check whether b is larger than the difference of the maximum value you can store in int minus the value of a. If a and/or b can be negative, you must (i) be careful not to get an overflow already for the difference check and (ii) perform a similar check for the minimum.

Product: Thats more difficult. I would split the integers into two half-length integers (i.e. if int is 32 bit, split it into two 16 bit numbers using bit-masking and shifting). Then do the multiplication, and then look whether the result fits into 32 bit.

Everything under the condition that you do not want to simply take long for the temporary result.

Solution 4

Suppose both a and b are positive or negative, and if the sign of a + b is not equal with the sign of a and b, then overflow happens. You can use this rule to judge whether overflow happens and throw an exception. When you catch this expcetion, you can deal it according to the method metioned in previous answers. Another method is to doing operation using largest range type which will not overflow. You can use long for the operation between Integers.

Share:
35,883
Michael
Author by

Michael

Scala (moslty) programmer

Updated on August 20, 2020

Comments

  • Michael
    Michael almost 4 years

    Possible Duplicate:
    How can I check if multiplying two numbers in Java will cause an overflow?

    Suppose I have a Java class method, which uses * and + operations.

    int foo(int a, int b) {
      ... // some calculations with + and * 
    }
    

    How to make sure that no overflow occurs in foo?

    I guess I can either use BigDecimal or replace all + and * with "wrappers" like:

    int sum(int a, int b) {
       int c = a + b;
       if (a > 0 && b > 0 && c < 0) 
         throw new MyOverfowException(a, b)
       return c;
    }
    
    int prod(int a, int b) {
       int c = a * b;
       if (a > 0 && b > 0 && c < 0) 
         throw new MyOverfowException(a, b)
       return c;
    }
    

    Are there better ways to make sure that no int overflow occurs in a Java method ?

  • Alnitak
    Alnitak almost 12 years
    the second of those is what my answer does
  • Rich
    Rich over 10 years
    "It is a difficult problem from an engineering perspective." -- It's not that difficult: just generate machine code to check the overflow register flag after every operation. That's what the C# "checked" block does. The issue is that Java doesn't offer that as an option, not because it is beyond the wit of man.
  • Stephen C
    Stephen C over 10 years
    @Rich - it is difficult if you are not in a position to modify the Java compiler. Most people aren't!
  • Rich
    Rich over 10 years
    lol, good point :-) It's frustrating that this wasn't included in the Java compiler. There isn't a nice easy answer (which is also correct) on this question or it's duplicate :-(
  • Rich
    Rich over 10 years
  • yitzih
    yitzih almost 8 years
    I know this answer is old, but this solution isn't guaranteed to work since the larger type itself can overflow and end up in a range that appears normal for the smaller type.
  • Alnitak
    Alnitak almost 8 years
    @yitzih you're wrong - the addition of two (positive) integers cannot exceed a value any more than 1 bit longer than the longest operand. There's no way given the constraints of the question to end up with a "larger type itself overflow"
  • Alnitak
    Alnitak almost 8 years
    @yitzihI I forgot that multiplication is also involved, but there too, the product of two 31 bit positive integers cannot exceed 62 bits.
  • yitzih
    yitzih almost 8 years
    that's a fair point. My mistake, thank you for clarifying.