8318915: Enhance checks in BigDecimal.toPlainString()

Reviewed-by: rriggs, bpb
This commit is contained in:
Raffaello Giulietti 2023-11-08 19:05:22 +00:00
parent 7d25f1c6cb
commit a6785e4d63
2 changed files with 57 additions and 20 deletions

View File

@ -3503,21 +3503,19 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
return "0";
}
int trailingZeros = checkScaleNonZero((-(long)scale));
StringBuilder buf;
if(intCompact!=INFLATED) {
buf = new StringBuilder(20+trailingZeros);
buf.append(intCompact);
} else {
String str = intVal.toString();
buf = new StringBuilder(str.length()+trailingZeros);
buf.append(str);
}
for (int i = 0; i < trailingZeros; i++) {
buf.append('0');
String str = intCompact != INFLATED
? Long.toString(intCompact)
: intVal.toString();
int len = str.length() + trailingZeros;
if (len < 0) {
throw new OutOfMemoryError("too large to fit in a String");
}
StringBuilder buf = new StringBuilder(len);
buf.append(str);
buf.repeat('0', trailingZeros);
return buf.toString();
}
String str ;
String str;
if(intCompact!=INFLATED) {
str = Long.toString(Math.abs(intCompact));
} else {
@ -3527,11 +3525,11 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
}
/* Returns a digit.digit string */
private String getValueString(int signum, String intString, int scale) {
private static String getValueString(int signum, String intString, int scale) {
/* Insert decimal point */
StringBuilder buf;
int insertionPoint = intString.length() - scale;
if (insertionPoint == 0) { /* Point goes right before intVal */
if (insertionPoint == 0) { /* Point goes just before intVal */
return (signum<0 ? "-0." : "0.") + intString;
} else if (insertionPoint > 0) { /* Point goes inside intVal */
buf = new StringBuilder(intString);
@ -3539,11 +3537,13 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
if (signum < 0)
buf.insert(0, '-');
} else { /* We must insert zeros between point and intVal */
buf = new StringBuilder(3-insertionPoint + intString.length());
buf.append(signum<0 ? "-0." : "0.");
for (int i=0; i<-insertionPoint; i++) {
buf.append('0');
int len = (signum < 0 ? 3 : 2) + scale;
if (len < 0) {
throw new OutOfMemoryError("too large to fit in a String");
}
buf = new StringBuilder(len);
buf.append(signum<0 ? "-0." : "0.");
buf.repeat('0', -insertionPoint); // insertionPoint != MIN_VALUE
buf.append(intString);
}
return buf.toString();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2004, 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 4984872
* @bug 4984872 8318915
* @summary Basic tests of toPlainString method
* @run main ToPlainStringTests
* @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 ToPlainStringTests
@ -67,6 +67,11 @@ public class ToPlainStringTests {
{"12345678901234567890", "12345678901234567890"},
{"12345678901234567890e22", "123456789012345678900000000000000000000000"},
{"12345678901234567890e-22", "0.0012345678901234567890"},
{"12345e-1", "1234.5"},
{"12345e-2", "123.45"},
{"12345e-3", "12.345"},
{"12345e-4", "1.2345"},
};
int errors = 0;
@ -89,6 +94,38 @@ public class ToPlainStringTests {
}
}
String[] failingCases = {
"1E-" + (Integer.MAX_VALUE - 0), // MAX_VALUE + 2 chars
"1E-" + (Integer.MAX_VALUE - 1), // MAX_VALUE + 1 chars
"-1E-" + (Integer.MAX_VALUE - 0), // MAX_VALUE + 3 chars
"-1E-" + (Integer.MAX_VALUE - 1), // MAX_VALUE + 2 chars
"-1E-" + (Integer.MAX_VALUE - 2), // MAX_VALUE + 1 chars
"123456789E-" + (Integer.MAX_VALUE - 0), // MAX_VALUE + 2 chars
"123456789E-" + (Integer.MAX_VALUE - 1), // MAX_VALUE + 1 chars
"-123456789E-" + (Integer.MAX_VALUE - 0), // MAX_VALUE + 3 chars
"-123456789E-" + (Integer.MAX_VALUE - 1), // MAX_VALUE + 2 chars
"-123456789E-" + (Integer.MAX_VALUE - 2), // MAX_VALUE + 1 chars
"1E" + Integer.MAX_VALUE, // MAX_VALUE + 1 chars
"123456789E" + Integer.MAX_VALUE, // MAX_VALUE + 9 chars
"-1E" + Integer.MAX_VALUE, // MAX_VALUE + 2 chars
"-123456789E" + Integer.MAX_VALUE, // MAX_VALUE + 10 chars
};
/* We expect pre-emptive OutOfMemoryErrors, nothing else */
for (String failingCase : failingCases) {
try {
new BigDecimal(failingCase).toPlainString();
} catch (OutOfMemoryError expected) {
continue;
} catch (Throwable ignored) {
}
++errors;
}
if(errors > 0)
throw new RuntimeException(errors + " errors during run.");
}