8305343: BigDecimal.fractionOnly() erroneously returns true for large scale value

Reviewed-by: darcy
This commit is contained in:
Raffaello Giulietti 2023-04-04 18:09:04 +00:00
parent dd59471798
commit 7c650489d2
2 changed files with 36 additions and 5 deletions

View File

@ -3596,7 +3596,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
*/
private boolean fractionOnly() {
assert this.signum() != 0;
return (this.precision() - this.scale) <= 0;
return this.precision() <= this.scale;
}
/**
@ -3624,8 +3624,15 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
if (fractionOnly())
throw new ArithmeticException("Rounding necessary");
// If more than 19 digits in integer part it cannot possibly fit
if ((precision() - scale) > 19) // [OK for negative scale too]
/*
* If more than 19 digits in integer part it cannot possibly fit.
* Ensure that arithmetic does not overflow, so instead of
* precision() - scale > 19
* prefer
* precision() - 19 > scale
* since precision() > 0, so the lhs cannot overflow.
*/
if (precision() - 19 > scale) // [OK for negative scale too]
throw new java.lang.ArithmeticException("Overflow");
// round to an integer, with Exception if decimal part non-0

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
/**
* @test
* @bug 6806261 8211936
* @bug 6806261 8211936 8305343
* @summary Tests of BigDecimal.longValueExact
*/
import java.math.*;
@ -37,6 +37,7 @@ public class LongValueExactTests {
failures += longValueExactSuccessful();
failures += longValueExactExceptional();
failures += longValueExactExceptional8305343();
if (failures > 0) {
throw new RuntimeException("Incurred " + failures +
@ -117,4 +118,27 @@ public class LongValueExactTests {
}
return failures;
}
private static int longValueExactExceptional8305343() {
int failures = 0;
List<BigDecimal> exceptionalCases =
List.of(new BigDecimal("1e" + (Integer.MAX_VALUE - 1)),
new BigDecimal("1e" + (Integer.MAX_VALUE))
);
for (BigDecimal bd : exceptionalCases) {
try {
bd.longValueExact();
failures++;
System.err.println("Unexpected non-exceptional longValueExact on " + bd);
} catch (ArithmeticException e) {
if (!e.getMessage().toLowerCase().contains("overflow")) {
failures++;
System.err.println("Unexpected non-exceptional longValueExact on " + bd);
}
}
}
return failures;
}
}