8253459: Formatter treats index, width and precision > Integer.MAX_VALUE incorrectly
Reviewed-by: rriggs, smarks
This commit is contained in:
parent
b9db002fef
commit
080c707aab
@ -692,12 +692,28 @@ import sun.util.locale.provider.ResourceBundleBasedAdapter;
|
||||
* <p> If the format specifier contains a width or precision with an invalid
|
||||
* value or which is otherwise unsupported, then a {@link
|
||||
* IllegalFormatWidthException} or {@link IllegalFormatPrecisionException}
|
||||
* respectively will be thrown.
|
||||
* respectively will be thrown. Similarly, values of zero for an argument
|
||||
* index will result in an {@link IllegalFormatException}.
|
||||
*
|
||||
* <p> If a format specifier contains a conversion character that is not
|
||||
* applicable to the corresponding argument, then an {@link
|
||||
* IllegalFormatConversionException} will be thrown.
|
||||
*
|
||||
* <p> Values of <i>precision</i> must be in the range zero to
|
||||
* {@link Integer#MAX_VALUE}, inclusive, otherwise
|
||||
* {@link IllegalFormatPrecisionException} is thrown.</p>
|
||||
*
|
||||
* <p> Values of <i>width</i> must be in the range one to
|
||||
* {@link Integer#MAX_VALUE}, inclusive, otherwise
|
||||
* {@link IllegalFormatWidthException} will be thrown
|
||||
* Note that widths can appear to have a negative value, but the negative sign
|
||||
* is a <i>flag</i>. For example in the format string {@code "%-20s"} the
|
||||
* <i>width</i> is <i>20</i> and the <i>flag</i> is "-".</p>
|
||||
*
|
||||
* <p> Values of <i>index</i> must be in the range one to
|
||||
* {@link Integer#MAX_VALUE}, inclusive, otherwise
|
||||
* {@link IllegalFormatException} will be thrown.</p>
|
||||
*
|
||||
* <p> All specified exceptions may be thrown by any of the {@code format}
|
||||
* methods of {@code Formatter} as well as by any {@code format} convenience
|
||||
* methods such as {@link String#format(String,Object...) String.format} and
|
||||
@ -2783,8 +2799,11 @@ public final class Formatter implements Closeable, Flushable {
|
||||
try {
|
||||
// skip the trailing '$'
|
||||
index = Integer.parseInt(s, start, end - 1, 10);
|
||||
if (index <= 0) {
|
||||
throw new IllegalFormatArgumentIndexException(index);
|
||||
}
|
||||
} catch (NumberFormatException x) {
|
||||
assert(false);
|
||||
throw new IllegalFormatArgumentIndexException(Integer.MIN_VALUE);
|
||||
}
|
||||
} else {
|
||||
index = 0;
|
||||
@ -2811,7 +2830,7 @@ public final class Formatter implements Closeable, Flushable {
|
||||
if (width < 0)
|
||||
throw new IllegalFormatWidthException(width);
|
||||
} catch (NumberFormatException x) {
|
||||
assert(false);
|
||||
throw new IllegalFormatWidthException(Integer.MIN_VALUE);
|
||||
}
|
||||
}
|
||||
return width;
|
||||
@ -2826,7 +2845,7 @@ public final class Formatter implements Closeable, Flushable {
|
||||
if (precision < 0)
|
||||
throw new IllegalFormatPrecisionException(precision);
|
||||
} catch (NumberFormatException x) {
|
||||
assert(false);
|
||||
throw new IllegalFormatPrecisionException(Integer.MIN_VALUE);
|
||||
}
|
||||
}
|
||||
return precision;
|
||||
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package java.util;
|
||||
|
||||
/**
|
||||
* Unchecked exception thrown when the argument index is not within the valid
|
||||
* range of supported argument index values. If an index value isn't
|
||||
* representable by an {@code int} type, then the value
|
||||
* {@code Integer.MIN_VALUE} will be used in the exception.
|
||||
*
|
||||
* @since 16
|
||||
*/
|
||||
class IllegalFormatArgumentIndexException extends IllegalFormatException {
|
||||
|
||||
@java.io.Serial
|
||||
private static final long serialVersionUID = 4191767811181838112L;
|
||||
|
||||
private final int illegalIndex;
|
||||
|
||||
/**
|
||||
* Constructs an instance of this class with the specified argument index
|
||||
* @param index The value of a corresponding illegal argument index.
|
||||
*/
|
||||
IllegalFormatArgumentIndexException(int index) {
|
||||
illegalIndex = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the illegal index.
|
||||
* Returns {@code Integer.MIN_VALUE} if the illegal index is not
|
||||
* representable by an {@code int}.
|
||||
* @return the illegal index value
|
||||
*/
|
||||
int getIndex() {
|
||||
return illegalIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
int index = getIndex();
|
||||
|
||||
if (index == Integer.MIN_VALUE) {
|
||||
return "Format argument index: (not representable as int)";
|
||||
}
|
||||
|
||||
return String.format("Illegal format argument index = %d", getIndex());
|
||||
}
|
||||
|
||||
}
|
@ -28,7 +28,9 @@ package java.util;
|
||||
/**
|
||||
* Unchecked exception thrown when the precision is a negative value other than
|
||||
* {@code -1}, the conversion does not support a precision, or the value is
|
||||
* otherwise unsupported.
|
||||
* otherwise unsupported. If the precision is not representable by an
|
||||
* {@code int} type, then the value {@code Integer.MIN_VALUE} will be used
|
||||
* in the exception.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
@ -50,7 +52,8 @@ public class IllegalFormatPrecisionException extends IllegalFormatException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the precision
|
||||
* Returns the precision. If the precision isn't representable by an
|
||||
* {@code int}, then will return {@code Integer.MIN_VALUE}.
|
||||
*
|
||||
* @return The precision
|
||||
*/
|
||||
|
@ -27,7 +27,9 @@ package java.util;
|
||||
|
||||
/**
|
||||
* Unchecked exception thrown when the format width is a negative value other
|
||||
* than {@code -1} or is otherwise unsupported.
|
||||
* than {@code -1} or is otherwise unsupported. If a given format width is not
|
||||
* representable by an {@code int} type, then the value
|
||||
* {@code Integer.MIN_VALUE} will be used in the exception.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
@ -49,7 +51,8 @@ public class IllegalFormatWidthException extends IllegalFormatException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width
|
||||
* Returns the width. If the width is not representable by an {@code int},
|
||||
* then returns {@code Integer.MIN_VALUE}.
|
||||
*
|
||||
* @return The width
|
||||
*/
|
||||
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 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 8253459
|
||||
* @run testng TestFormatSpecifierBounds
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
@Test
|
||||
public class TestFormatSpecifierBounds {
|
||||
|
||||
public void testZeroIndex() {
|
||||
IllegalFormatException e = expectThrows(IllegalFormatException.class, () -> {
|
||||
String r = String.format("%0$s", "A", "B");
|
||||
});
|
||||
assertEquals(e.getMessage(), "Illegal format argument index = 0");
|
||||
}
|
||||
|
||||
public void testNonRepresentableIntIndex() {
|
||||
IllegalFormatException e = expectThrows(IllegalFormatException.class, () -> {
|
||||
String r = String.format("%2147483648$s", "A", "B");
|
||||
});
|
||||
assertEquals(e.getMessage(), "Format argument index: (not representable as int)");
|
||||
}
|
||||
|
||||
public void testZeroWidth() {
|
||||
assertThrows(IllegalFormatException.class, () -> {
|
||||
String r = String.format("%0s", "A", "B");
|
||||
});
|
||||
}
|
||||
|
||||
public void testNonRepresentableWidth() {
|
||||
IllegalFormatException e = expectThrows(IllegalFormatException.class, () -> {
|
||||
String r = String.format("%2147483648s", "A", "B");
|
||||
});
|
||||
assertEquals(e.getMessage(), Integer.toString(Integer.MIN_VALUE));
|
||||
}
|
||||
|
||||
public void testNonRepresentablePrecision() {
|
||||
IllegalFormatException e = expectThrows(IllegalFormatException.class, () -> {
|
||||
String r = String.format("%.2147483648s", "A", "B");
|
||||
});
|
||||
assertEquals(e.getMessage(), Integer.toString(Integer.MIN_VALUE));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user