diff --git a/src/java.base/share/classes/java/math/BigDecimal.java b/src/java.base/share/classes/java/math/BigDecimal.java index f5462a77a8c..70a9b10f456 100644 --- a/src/java.base/share/classes/java/math/BigDecimal.java +++ b/src/java.base/share/classes/java/math/BigDecimal.java @@ -3596,7 +3596,7 @@ public class BigDecimal extends Number implements Comparable { */ 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 { 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 diff --git a/test/jdk/java/math/BigDecimal/LongValueExactTests.java b/test/jdk/java/math/BigDecimal/LongValueExactTests.java index 7a6ad0b580c..b6dc5a33dee 100644 --- a/test/jdk/java/math/BigDecimal/LongValueExactTests.java +++ b/test/jdk/java/math/BigDecimal/LongValueExactTests.java @@ -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 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; + } + }