Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8253459: Formatter treats index, width and precision > Integer.MAX_VALUE incorrectly #516

Closed
wants to merge 13 commits into from
@@ -692,12 +692,28 @@
* <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

This comment has been minimized.

@Marcono1234

Marcono1234 Oct 25, 2020

Hi @Marcono1234, thanks for making a comment in an OpenJDK project!

All comments and discussions in the OpenJDK Community must be made available under the OpenJDK Terms of Use. If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please Use "Add GitHub user Marcono1234 for the summary.

If you are not an OpenJDK Author, Committer or Reviewer, simply check the box below to accept the OpenJDK Terms of Use for your comments.

Your comment will be automatically restored once you have accepted the OpenJDK Terms of Use.

* 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>

This comment has been minimized.

@Marcono1234

Marcono1234 Oct 25, 2020

Hi @Marcono1234, thanks for making a comment in an OpenJDK project!

All comments and discussions in the OpenJDK Community must be made available under the OpenJDK Terms of Use. If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please Use "Add GitHub user Marcono1234 for the summary.

If you are not an OpenJDK Author, Committer or Reviewer, simply check the box below to accept the OpenJDK Terms of Use for your comments.

Your comment will be automatically restored once you have accepted the OpenJDK Terms of Use.

*
* <p> Values of <i>index</i> must be in the range one to

This comment has been minimized.

@Marcono1234

Marcono1234 Oct 25, 2020

Hi @Marcono1234, thanks for making a comment in an OpenJDK project!

All comments and discussions in the OpenJDK Community must be made available under the OpenJDK Terms of Use. If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please Use "Add GitHub user Marcono1234 for the summary.

If you are not an OpenJDK Author, Committer or Reviewer, simply check the box below to accept the OpenJDK Terms of Use for your comments.

Your comment will be automatically restored once you have accepted the OpenJDK Terms of Use.

* {@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 @@ private int index(String s, int start, int end) {
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 @@ private int width(String s, int start, int end) {
if (width < 0)
throw new IllegalFormatWidthException(width);
} catch (NumberFormatException x) {
assert(false);
throw new IllegalFormatWidthException(Integer.MIN_VALUE);
}
}
return width;
@@ -2826,7 +2845,7 @@ private int precision(String s, int start, int end) {
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.

This comment has been minimized.

@Marcono1234

Marcono1234 Oct 25, 2020

Hi @Marcono1234, thanks for making a comment in an OpenJDK project!

All comments and discussions in the OpenJDK Community must be made available under the OpenJDK Terms of Use. If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please Use "Add GitHub user Marcono1234 for the summary.

If you are not an OpenJDK Author, Committer or Reviewer, simply check the box below to accept the OpenJDK Terms of Use for your comments.

Your comment will be automatically restored once you have accepted the OpenJDK Terms of Use.

*
* @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.

This comment has been minimized.

@Marcono1234

Marcono1234 Oct 25, 2020

Hi @Marcono1234, thanks for making a comment in an OpenJDK project!

All comments and discussions in the OpenJDK Community must be made available under the OpenJDK Terms of Use. If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please Use "Add GitHub user Marcono1234 for the summary.

If you are not an OpenJDK Author, Committer or Reviewer, simply check the box below to accept the OpenJDK Terms of Use for your comments.

Your comment will be automatically restored once you have accepted the OpenJDK Terms of Use.

* Returns {@code Integer.MIN_VALUE} if the illegal index is not

This comment has been minimized.

@Marcono1234

Marcono1234 Oct 25, 2020

Hi @Marcono1234, thanks for making a comment in an OpenJDK project!

All comments and discussions in the OpenJDK Community must be made available under the OpenJDK Terms of Use. If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please Use "Add GitHub user Marcono1234 for the summary.

If you are not an OpenJDK Author, Committer or Reviewer, simply check the box below to accept the OpenJDK Terms of Use for your comments.

Your comment will be automatically restored once you have accepted the OpenJDK Terms of Use.

* 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());
}

This comment has been minimized.

@RogerRiggs

RogerRiggs Nov 17, 2020
Contributor

The exception with a very large negative number isn't going to easy to recognize.
Can the exception message say (for the Integer.MIN_VALUE) that the index is not valid index.
Its probably too much to ask have an indication where in the format string the offending index occurs.


}
@@ -28,7 +28,9 @@
/**
* 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

This comment has been minimized.

@Marcono1234

Marcono1234 Oct 25, 2020

Hi @Marcono1234, thanks for making a comment in an OpenJDK project!

All comments and discussions in the OpenJDK Community must be made available under the OpenJDK Terms of Use. If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please Use "Add GitHub user Marcono1234 for the summary.

If you are not an OpenJDK Author, Committer or Reviewer, simply check the box below to accept the OpenJDK Terms of Use for your comments.

Your comment will be automatically restored once you have accepted the OpenJDK Terms of Use.

* 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

This comment has been minimized.

@Marcono1234

Marcono1234 Oct 25, 2020

Hi @Marcono1234, thanks for making a comment in an OpenJDK project!

All comments and discussions in the OpenJDK Community must be made available under the OpenJDK Terms of Use. If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please Use "Add GitHub user Marcono1234 for the summary.

If you are not an OpenJDK Author, Committer or Reviewer, simply check the box below to accept the OpenJDK Terms of Use for your comments.

Your comment will be automatically restored once you have accepted the OpenJDK Terms of Use.

* in the exception.
*
* @since 1.5
*/
@@ -50,7 +52,8 @@ public IllegalFormatPrecisionException(int p) {
}

/**
* 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 @@

/**
* 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

This comment has been minimized.

@Marcono1234

Marcono1234 Oct 25, 2020

Hi @Marcono1234, thanks for making a comment in an OpenJDK project!

All comments and discussions in the OpenJDK Community must be made available under the OpenJDK Terms of Use. If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please Use "Add GitHub user Marcono1234 for the summary.

If you are not an OpenJDK Author, Committer or Reviewer, simply check the box below to accept the OpenJDK Terms of Use for your comments.

Your comment will be automatically restored once you have accepted the OpenJDK Terms of Use.

* representable by an {@code int} type, then the value
* {@code Integer.MIN_VALUE} will be used in the exception.

This comment has been minimized.

@Marcono1234

Marcono1234 Oct 25, 2020

Hi @Marcono1234, thanks for making a comment in an OpenJDK project!

All comments and discussions in the OpenJDK Community must be made available under the OpenJDK Terms of Use. If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please Use "Add GitHub user Marcono1234 for the summary.

If you are not an OpenJDK Author, Committer or Reviewer, simply check the box below to accept the OpenJDK Terms of Use for your comments.

Your comment will be automatically restored once you have accepted the OpenJDK Terms of Use.

*
* @since 1.5
*/
@@ -49,7 +51,8 @@ public IllegalFormatWidthException(int w) {
}

/**
* Returns the width
* Returns the width. If the width is not representable by an {@code int},
* then returns {@code Integer.MIN_VALUE}.

This comment has been minimized.

@Marcono1234

Marcono1234 Oct 25, 2020

Hi @Marcono1234, thanks for making a comment in an OpenJDK project!

All comments and discussions in the OpenJDK Community must be made available under the OpenJDK Terms of Use. If you already are an OpenJDK Author, Committer or Reviewer, please click here to open a new issue so that we can record that fact. Please Use "Add GitHub user Marcono1234 for the summary.

If you are not an OpenJDK Author, Committer or Reviewer, simply check the box below to accept the OpenJDK Terms of Use for your comments.

Your comment will be automatically restored once you have accepted the OpenJDK Terms of Use.

*
* @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));
}
}