From 33412c102ce799ff2de3512df77e6e07d76acd36 Mon Sep 17 00:00:00 2001 From: Raffaello Giulietti Date: Thu, 12 Jan 2023 19:21:09 +0000 Subject: [PATCH] 8299677: Formatter.format might take a long time to format an integer or floating-point Reviewed-by: alanb, stsypanov, darcy --- .../share/classes/java/util/Formatter.java | 9 +- test/jdk/java/util/Formatter/Padding.java | 313 ++++++++++++++++++ 2 files changed, 317 insertions(+), 5 deletions(-) create mode 100644 test/jdk/java/util/Formatter/Padding.java diff --git a/src/java.base/share/classes/java/util/Formatter.java b/src/java.base/share/classes/java/util/Formatter.java index 5c5859c767dc3..b6ca8fb3b6572 100644 --- a/src/java.base/share/classes/java/util/Formatter.java +++ b/src/java.base/share/classes/java/util/Formatter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -4596,10 +4596,9 @@ private StringBuilder localizedMagnitude(Formatter fmt, StringBuilder sb, } // apply zero padding - if (width != -1 && Flags.contains(f, Flags.ZERO_PAD)) { - for (int k = sb.length(); k < width; k++) { - sb.insert(begin, zero); - } + if (width > sb.length() && Flags.contains(f, Flags.ZERO_PAD)) { + String zeros = String.valueOf(zero).repeat(width - sb.length()); + sb.insert(begin, zeros); } return sb; diff --git a/test/jdk/java/util/Formatter/Padding.java b/test/jdk/java/util/Formatter/Padding.java new file mode 100644 index 0000000000000..982b696792838 --- /dev/null +++ b/test/jdk/java/util/Formatter/Padding.java @@ -0,0 +1,313 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4906370 + * @summary Tests to excercise padding on int and double values, + * with various flag combinations. + * @run junit Padding + */ + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +public class Padding { + + static Arguments[] padding() { + return new Arguments[] { + /* blank padding, right adjusted, optional plus sign */ + arguments("12", "%1d", 12), + arguments("12", "%2d", 12), + arguments(" 12", "%3d", 12), + arguments(" 12", "%4d", 12), + arguments(" 12", "%5d", 12), + arguments(" 12", "%10d", 12), + + arguments("-12", "%1d", -12), + arguments("-12", "%2d", -12), + arguments("-12", "%3d", -12), + arguments(" -12", "%4d", -12), + arguments(" -12", "%5d", -12), + arguments(" -12", "%10d", -12), + + arguments("1.2", "%1.1f", 1.2), + arguments("1.2", "%2.1f", 1.2), + arguments("1.2", "%3.1f", 1.2), + arguments(" 1.2", "%4.1f", 1.2), + arguments(" 1.2", "%5.1f", 1.2), + arguments(" 1.2", "%10.1f", 1.2), + + arguments("-1.2", "%1.1f", -1.2), + arguments("-1.2", "%2.1f", -1.2), + arguments("-1.2", "%3.1f", -1.2), + arguments("-1.2", "%4.1f", -1.2), + arguments(" -1.2", "%5.1f", -1.2), + arguments(" -1.2", "%10.1f", -1.2), + + /* blank padding, right adjusted, mandatory plus sign */ + arguments("+12", "%+1d", 12), + arguments("+12", "%+2d", 12), + arguments("+12", "%+3d", 12), + arguments(" +12", "%+4d", 12), + arguments(" +12", "%+5d", 12), + arguments(" +12", "%+10d", 12), + + arguments("-12", "%+1d", -12), + arguments("-12", "%+2d", -12), + arguments("-12", "%+3d", -12), + arguments(" -12", "%+4d", -12), + arguments(" -12", "%+5d", -12), + arguments(" -12", "%+10d", -12), + + arguments("+1.2", "%+1.1f", 1.2), + arguments("+1.2", "%+2.1f", 1.2), + arguments("+1.2", "%+3.1f", 1.2), + arguments("+1.2", "%+4.1f", 1.2), + arguments(" +1.2", "%+5.1f", 1.2), + arguments(" +1.2", "%+10.1f", 1.2), + + arguments("-1.2", "%+1.1f", -1.2), + arguments("-1.2", "%+2.1f", -1.2), + arguments("-1.2", "%+3.1f", -1.2), + arguments("-1.2", "%+4.1f", -1.2), + arguments(" -1.2", "%+5.1f", -1.2), + arguments(" -1.2", "%+10.1f", -1.2), + + /* blank padding, right adjusted, mandatory blank sign */ + arguments(" 12", "% 1d", 12), + arguments(" 12", "% 2d", 12), + arguments(" 12", "% 3d", 12), + arguments(" 12", "% 4d", 12), + arguments(" 12", "% 5d", 12), + arguments(" 12", "% 10d", 12), + + arguments("-12", "% 1d", -12), + arguments("-12", "% 2d", -12), + arguments("-12", "% 3d", -12), + arguments(" -12", "% 4d", -12), + arguments(" -12", "% 5d", -12), + arguments(" -12", "% 10d", -12), + + arguments(" 1.2", "% 1.1f", 1.2), + arguments(" 1.2", "% 2.1f", 1.2), + arguments(" 1.2", "% 3.1f", 1.2), + arguments(" 1.2", "% 4.1f", 1.2), + arguments(" 1.2", "% 5.1f", 1.2), + arguments(" 1.2", "% 10.1f", 1.2), + + arguments("-1.2", "% 1.1f", -1.2), + arguments("-1.2", "% 2.1f", -1.2), + arguments("-1.2", "% 3.1f", -1.2), + arguments("-1.2", "% 4.1f", -1.2), + arguments(" -1.2", "% 5.1f", -1.2), + arguments(" -1.2", "% 10.1f", -1.2), + + /* blank padding, left adjusted, optional sign */ + arguments("12", "%-1d", 12), + arguments("12", "%-2d", 12), + arguments("12 ", "%-3d", 12), + arguments("12 ", "%-4d", 12), + arguments("12 ", "%-5d", 12), + arguments("12 ", "%-10d", 12), + + arguments("-12", "%-1d", -12), + arguments("-12", "%-2d", -12), + arguments("-12", "%-3d", -12), + arguments("-12 ", "%-4d", -12), + arguments("-12 ", "%-5d", -12), + arguments("-12 ", "%-10d", -12), + + arguments("1.2", "%-1.1f", 1.2), + arguments("1.2", "%-2.1f", 1.2), + arguments("1.2", "%-3.1f", 1.2), + arguments("1.2 ", "%-4.1f", 1.2), + arguments("1.2 ", "%-5.1f", 1.2), + arguments("1.2 ", "%-10.1f", 1.2), + + arguments("-1.2", "%-1.1f", -1.2), + arguments("-1.2", "%-2.1f", -1.2), + arguments("-1.2", "%-3.1f", -1.2), + arguments("-1.2", "%-4.1f", -1.2), + arguments("-1.2 ", "%-5.1f", -1.2), + arguments("-1.2 ", "%-10.1f", -1.2), + + /* blank padding, left adjusted, mandatory plus sign */ + arguments("+12", "%-+1d", 12), + arguments("+12", "%-+2d", 12), + arguments("+12", "%-+3d", 12), + arguments("+12 ", "%-+4d", 12), + arguments("+12 ", "%-+5d", 12), + arguments("+12 ", "%-+10d", 12), + + arguments("-12", "%-+1d", -12), + arguments("-12", "%-+2d", -12), + arguments("-12", "%-+3d", -12), + arguments("-12 ", "%-+4d", -12), + arguments("-12 ", "%-+5d", -12), + arguments("-12 ", "%-+10d", -12), + + arguments("+1.2", "%-+1.1f", 1.2), + arguments("+1.2", "%-+2.1f", 1.2), + arguments("+1.2", "%-+3.1f", 1.2), + arguments("+1.2", "%-+4.1f", 1.2), + arguments("+1.2 ", "%-+5.1f", 1.2), + arguments("+1.2 ", "%-+10.1f", 1.2), + + arguments("-1.2", "%-+1.1f", -1.2), + arguments("-1.2", "%-+2.1f", -1.2), + arguments("-1.2", "%-+3.1f", -1.2), + arguments("-1.2", "%-+4.1f", -1.2), + arguments("-1.2 ", "%-+5.1f", -1.2), + arguments("-1.2 ", "%-+10.1f", -1.2), + + /* blank padding, left adjusted, mandatory blank sign */ + arguments(" 12", "%- 1d", 12), + arguments(" 12", "%- 2d", 12), + arguments(" 12", "%- 3d", 12), + arguments(" 12 ", "%- 4d", 12), + arguments(" 12 ", "%- 5d", 12), + arguments(" 12 ", "%- 10d", 12), + + arguments("-12", "%- 1d", -12), + arguments("-12", "%- 2d", -12), + arguments("-12", "%- 3d", -12), + arguments("-12 ", "%- 4d", -12), + arguments("-12 ", "%- 5d", -12), + arguments("-12 ", "%- 10d", -12), + + arguments(" 1.2", "%- 1.1f", 1.2), + arguments(" 1.2", "%- 2.1f", 1.2), + arguments(" 1.2", "%- 3.1f", 1.2), + arguments(" 1.2", "%- 4.1f", 1.2), + arguments(" 1.2 ", "%- 5.1f", 1.2), + arguments(" 1.2 ", "%- 10.1f", 1.2), + + arguments("-1.2", "%- 1.1f", -1.2), + arguments("-1.2", "%- 2.1f", -1.2), + arguments("-1.2", "%- 3.1f", -1.2), + arguments("-1.2", "%- 4.1f", -1.2), + arguments("-1.2 ", "%- 5.1f", -1.2), + arguments("-1.2 ", "%- 10.1f", -1.2), + + /* zero padding, right adjusted, optional sign */ + arguments("12", "%01d", 12), + arguments("12", "%02d", 12), + arguments("012", "%03d", 12), + arguments("0012", "%04d", 12), + arguments("00012", "%05d", 12), + arguments("0000000012", "%010d", 12), + + arguments("-12", "%01d", -12), + arguments("-12", "%02d", -12), + arguments("-12", "%03d", -12), + arguments("-012", "%04d", -12), + arguments("-0012", "%05d", -12), + arguments("-000000012", "%010d", -12), + + arguments("1.2", "%01.1f", 1.2), + arguments("1.2", "%02.1f", 1.2), + arguments("1.2", "%03.1f", 1.2), + arguments("01.2", "%04.1f", 1.2), + arguments("001.2", "%05.1f", 1.2), + arguments("00000001.2", "%010.1f", 1.2), + + arguments("-1.2", "%01.1f", -1.2), + arguments("-1.2", "%02.1f", -1.2), + arguments("-1.2", "%03.1f", -1.2), + arguments("-1.2", "%04.1f", -1.2), + arguments("-01.2", "%05.1f", -1.2), + arguments("-0000001.2", "%010.1f", -1.2), + + /* zero padding, right adjusted, mandatory plus sign */ + arguments("+12", "%+01d", 12), + arguments("+12", "%+02d", 12), + arguments("+12", "%+03d", 12), + arguments("+012", "%+04d", 12), + arguments("+0012", "%+05d", 12), + arguments("+000000012", "%+010d", 12), + + arguments("-12", "%+01d", -12), + arguments("-12", "%+02d", -12), + arguments("-12", "%+03d", -12), + arguments("-012", "%+04d", -12), + arguments("-0012", "%+05d", -12), + arguments("-000000012", "%+010d", -12), + + arguments("+1.2", "%+01.1f", 1.2), + arguments("+1.2", "%+02.1f", 1.2), + arguments("+1.2", "%+03.1f", 1.2), + arguments("+1.2", "%+04.1f", 1.2), + arguments("+01.2", "%+05.1f", 1.2), + arguments("+0000001.2", "%+010.1f", 1.2), + + arguments("-1.2", "%+01.1f", -1.2), + arguments("-1.2", "%+02.1f", -1.2), + arguments("-1.2", "%+03.1f", -1.2), + arguments("-1.2", "%+04.1f", -1.2), + arguments("-01.2", "%+05.1f", -1.2), + arguments("-0000001.2", "%+010.1f", -1.2), + + /* zero padding, right adjusted, mandatory blank sign */ + arguments(" 12", "% 01d", 12), + arguments(" 12", "% 02d", 12), + arguments(" 12", "% 03d", 12), + arguments(" 012", "% 04d", 12), + arguments(" 0012", "% 05d", 12), + arguments(" 000000012", "% 010d", 12), + + arguments("-12", "% 01d", -12), + arguments("-12", "% 02d", -12), + arguments("-12", "% 03d", -12), + arguments("-012", "% 04d", -12), + arguments("-0012", "% 05d", -12), + arguments("-000000012", "% 010d", -12), + + arguments(" 1.2", "% 01.1f", 1.2), + arguments(" 1.2", "% 02.1f", 1.2), + arguments(" 1.2", "% 03.1f", 1.2), + arguments(" 1.2", "% 04.1f", 1.2), + arguments(" 01.2", "% 05.1f", 1.2), + arguments(" 0000001.2", "% 010.1f", 1.2), + + arguments("-1.2", "% 01.1f", -1.2), + arguments("-1.2", "% 02.1f", -1.2), + arguments("-1.2", "% 03.1f", -1.2), + arguments("-1.2", "% 04.1f", -1.2), + arguments("-01.2", "% 05.1f", -1.2), + arguments("-0000001.2", "% 010.1f", -1.2), + + }; + } + + @ParameterizedTest + @MethodSource + void padding(String expected, String format, Object value) { + assertEquals(expected, String.format(format, value)); + } + +}