Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java BigDecimal Possible Overflow Bug

I was testing boundary conditions on some code involving a BigDecimal, and I noticed that when a BigDecimal is initialized with the String "1e2147483647" it behaves unexpectedly. It seems to have a value between 0 and 1e-2147483647. When I try calling intValue(), I get a NegativeArraySizeException. I should note that 2147483647 is the max value of an integer on my system. Am I doing something wrong, or is this a problem with BigDecimal?

BigDecimal test = new BigDecimal("1e2147483647");  test.compareTo(new BigDecimal(0));  //Returns 1 test.compareTo(new BigDecimal("1e-2147483647"));  //Returns -1 test.intValue();  //Throws NegativeArraySizeException 
like image 418
DJMatch3000 Avatar asked Jul 01 '15 19:07

DJMatch3000


People also ask

Is BigDecimal immutable in Java?

Since BigDecimal is immutable, these operations do not modify the existing objects. Rather, they return new objects.

Does BigDecimal have a limit?

The limit is 32 * 2^32-1 bits for BigInteger or about 2^(4 billion). have a string with illegal digits.

What is the size of BigDecimal in Java?

A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale.

How much space does a BigDecimal take?

Assuming you don't call . toString() , it will remain zero bytes. Hence BigDecimal is (8+4+4)=16 bytes + BigInteger . BigInteger itself is 4+4+4+4+4=20 bytes + mag .


1 Answers

No, you appear to have a legit bug. The bug presents in JDK7 but fixed in JDK8. Your values are correctly representable as BigDecimals, and should behave correctly, but don't.

Tracing through the source code of BigDecimal, on line 2585, this.precision() is 1, and this.scale is -2147483647. this.precision() - this.scale therefore overflows, and the following overflow is not handled correctly.

This bug has been fixed in JDK8 by doing the subtraction in long arithmetic.

like image 68
Louis Wasserman Avatar answered Sep 21 '22 13:09

Louis Wasserman