Java BigDecimal可能存在溢出漏洞

78

我在测试一些涉及到BigDecimal的代码边界条件时,注意到当使用字符串"1e2147483647"初始化BigDecimal时,它的行为出现了意外。它的值似乎介于01e-2147483647之间。当我尝试调用intValue()时,会出现NegativeArraySizeException。需要注意的是,在我的系统上,2147483647是整数的最大值。我是否做错了什么,还是这是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

http://stackoverflow.com/questions/17945985/what-are-the-limits-of-bigdecimal-and-biginteger - kosa
谢谢,我还没有看到那个问题。我只是惊讶于构造函数没有像一个比它大一位数的数字那样抛出NumberFormatException异常。 - DJMatch3000
这更像是一个建议,而不是已知的事实,但1e-2147483647是一个非常大的数字。准确来说,log_2(10^2147483647) / 8 / 1024^3 = 0.83...应该能够计算出表示这样一个大整数所需的最小大小(以Gigabytes为单位)。也许这是一些内存分配问题吗? - Turing85
3
不,你的输入是有效和可表示的,尽管那是你可以为 "BigDecimal" 表示的最大指数。你的 bug 是合法的。 - Louis Wasserman
1个回答

87

不,你似乎遇到了一个真正的 bug。这个 bug 在 JDK7 中出现,但在 JDK8 中得到了修复。你的值可以正确地表示为 BigDecimal,并且应该能够正确地运行,但事实并非如此。

通过 BigDecimal 的源代码 进行跟踪,在第 2585 行,this.precision() 是 1,而 this.scale-2147483647。因此,this.precision() - this.scale 溢出了,并且以下溢出没有被正确处理。

JDK8 已经修复 了这个 bug,通过使用 long 算术进行减法计算


这在Android 17的Java中可以实现吗(类似于JDK6)? - Ky -

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接