8166261: Scanner.nextInt(int) (and similar methods) throws PatternSyntaxException
Reviewed-by: naoto
--- a/jdk/src/java.base/share/classes/java/util/Scanner.java Mon Oct 31 16:41:41 2016 +0800
+++ b/jdk/src/java.base/share/classes/java/util/Scanner.java Mon Oct 31 10:34:31 2016 -0700
@@ -1267,6 +1267,9 @@
// The next operation should occur in the specified radix but
// the default is left untouched.
private void setRadix(int radix) {
+ if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX))
+ throw new IllegalArgumentException("radix:"+radix);
+
if (this.radix != radix) {
// Force rebuilding and recompilation of radix dependent patterns
integerPattern = null;
@@ -1811,10 +1814,15 @@
* interpreted as a byte value in the specified radix using the
* {@link #nextByte} method. The scanner does not advance past any input.
*
+ * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+ * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+ * {@code IllegalArgumentException} is thrown.
+ *
* @param radix the radix used to interpret the token as a byte value
* @return true if and only if this scanner's next token is a valid
* byte value
* @throws IllegalStateException if this scanner is closed
+ * @throws IllegalArgumentException if the radix is out of range
*/
public boolean hasNextByte(int radix) {
setRadix(radix);
@@ -1869,6 +1877,10 @@
* {@link Byte#parseByte(String, int) Byte.parseByte} with the
* specified radix.
*
+ * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+ * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+ * {@code IllegalArgumentException} is thrown.
+ *
* @param radix the radix used to interpret the token as a byte value
* @return the {@code byte} scanned from the input
* @throws InputMismatchException
@@ -1876,6 +1888,7 @@
* regular expression, or is out of range
* @throws NoSuchElementException if input is exhausted
* @throws IllegalStateException if this scanner is closed
+ * @throws IllegalArgumentException if the radix is out of range
*/
public byte nextByte(int radix) {
// Check cached result
@@ -1917,10 +1930,15 @@
* interpreted as a short value in the specified radix using the
* {@link #nextShort} method. The scanner does not advance past any input.
*
+ * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+ * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+ * {@code IllegalArgumentException} is thrown.
+ *
* @param radix the radix used to interpret the token as a short value
* @return true if and only if this scanner's next token is a valid
* short value in the specified radix
* @throws IllegalStateException if this scanner is closed
+ * @throws IllegalArgumentException if the radix is out of range
*/
public boolean hasNextShort(int radix) {
setRadix(radix);
@@ -1975,6 +1993,10 @@
* {@link Short#parseShort(String, int) Short.parseShort} with the
* specified radix.
*
+ * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+ * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+ * {@code IllegalArgumentException} is thrown.
+ *
* @param radix the radix used to interpret the token as a short value
* @return the {@code short} scanned from the input
* @throws InputMismatchException
@@ -1982,6 +2004,7 @@
* regular expression, or is out of range
* @throws NoSuchElementException if input is exhausted
* @throws IllegalStateException if this scanner is closed
+ * @throws IllegalArgumentException if the radix is out of range
*/
public short nextShort(int radix) {
// Check cached result
@@ -2023,10 +2046,15 @@
* interpreted as an int value in the specified radix using the
* {@link #nextInt} method. The scanner does not advance past any input.
*
+ * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+ * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+ * {@code IllegalArgumentException} is thrown.
+ *
* @param radix the radix used to interpret the token as an int value
* @return true if and only if this scanner's next token is a valid
* int value
* @throws IllegalStateException if this scanner is closed
+ * @throws IllegalArgumentException if the radix is out of range
*/
public boolean hasNextInt(int radix) {
setRadix(radix);
@@ -2105,6 +2133,10 @@
* {@link Integer#parseInt(String, int) Integer.parseInt} with the
* specified radix.
*
+ * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+ * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+ * {@code IllegalArgumentException} is thrown.
+ *
* @param radix the radix used to interpret the token as an int value
* @return the {@code int} scanned from the input
* @throws InputMismatchException
@@ -2112,6 +2144,7 @@
* regular expression, or is out of range
* @throws NoSuchElementException if input is exhausted
* @throws IllegalStateException if this scanner is closed
+ * @throws IllegalArgumentException if the radix is out of range
*/
public int nextInt(int radix) {
// Check cached result
@@ -2153,10 +2186,15 @@
* interpreted as a long value in the specified radix using the
* {@link #nextLong} method. The scanner does not advance past any input.
*
+ * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+ * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+ * {@code IllegalArgumentException} is thrown.
+ *
* @param radix the radix used to interpret the token as a long value
* @return true if and only if this scanner's next token is a valid
* long value
* @throws IllegalStateException if this scanner is closed
+ * @throws IllegalArgumentException if the radix is out of range
*/
public boolean hasNextLong(int radix) {
setRadix(radix);
@@ -2211,6 +2249,10 @@
* {@link Long#parseLong(String, int) Long.parseLong} with the
* specified radix.
*
+ * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+ * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+ * {@code IllegalArgumentException} is thrown.
+ *
* @param radix the radix used to interpret the token as an int value
* @return the {@code long} scanned from the input
* @throws InputMismatchException
@@ -2218,6 +2260,7 @@
* regular expression, or is out of range
* @throws NoSuchElementException if input is exhausted
* @throws IllegalStateException if this scanner is closed
+ * @throws IllegalArgumentException if the radix is out of range
*/
public long nextLong(int radix) {
// Check cached result
@@ -2450,10 +2493,15 @@
* the {@link #nextBigInteger} method. The scanner does not advance past
* any input.
*
+ * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+ * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+ * {@code IllegalArgumentException} is thrown.
+ *
* @param radix the radix used to interpret the token as an integer
* @return true if and only if this scanner's next token is a valid
* {@code BigInteger}
* @throws IllegalStateException if this scanner is closed
+ * @throws IllegalArgumentException if the radix is out of range
*/
public boolean hasNextBigInteger(int radix) {
setRadix(radix);
@@ -2504,6 +2552,10 @@
* java.math.BigInteger#BigInteger(java.lang.String)
* BigInteger(String, int)} constructor with the specified radix.
*
+ * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+ * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+ * {@code IllegalArgumentException} is thrown.
+ *
* @param radix the radix used to interpret the token
* @return the {@code BigInteger} scanned from the input
* @throws InputMismatchException
@@ -2511,6 +2563,7 @@
* regular expression, or is out of range
* @throws NoSuchElementException if the input is exhausted
* @throws IllegalStateException if this scanner is closed
+ * @throws IllegalArgumentException if the radix is out of range
*/
public BigInteger nextBigInteger(int radix) {
// Check cached result
--- a/jdk/test/java/util/Scanner/ScanTest.java Mon Oct 31 16:41:41 2016 +0800
+++ b/jdk/test/java/util/Scanner/ScanTest.java Mon Oct 31 10:34:31 2016 -0700
@@ -24,7 +24,7 @@
/**
* @test
* @bug 4313885 4926319 4927634 5032610 5032622 5049968 5059533 6223711 6277261 6269946 6288823
- * 8072722 8139414
+ * 8072722 8139414 8166261
* @summary Basic tests of java.util.Scanner methods
* @key randomness
* @modules jdk.localedata
@@ -36,6 +36,7 @@
import java.nio.*;
import java.text.*;
import java.util.*;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.regex.*;
import java.util.stream.*;
@@ -79,6 +80,7 @@
resetTest();
streamCloseTest();
streamComodTest();
+ outOfRangeRadixTest();
for (int j = 0; j < NUM_SOURCE_TYPES; j++) {
hasNextTest(j);
@@ -1509,6 +1511,48 @@
report("Reset test");
}
+ static List<BiConsumer <Scanner, Integer>> methodWRList = Arrays.asList(
+ (s, r) -> s.hasNextByte(r),
+ (s, r) -> s.nextByte(r),
+ (s, r) -> s.hasNextShort(r),
+ (s, r) -> s.nextShort(r),
+ (s, r) -> s.hasNextInt(r),
+ (s, r) -> s.nextInt(r),
+ (s, r) -> s.hasNextLong(r),
+ (s, r) -> s.nextLong(r),
+ (s, r) -> s.hasNextBigInteger(r),
+ (s, r) -> s.nextBigInteger(r)
+ );
+
+ /*
+ * Test that setting the radix to an out of range value triggers
+ * an IllegalArgumentException
+ */
+ public static void outOfRangeRadixTest() throws Exception {
+ int[] bad = new int[] { -1, 0, 1, 37, 38 };
+ int[] good = IntStream.rangeClosed(Character.MIN_RADIX, Character.MAX_RADIX)
+ .toArray();
+
+ methodWRList.stream().forEach( m -> {
+ for (int r : bad) {
+ try (Scanner sc = new Scanner("10 10 10 10")) {
+ m.accept(sc, r);
+ failCount++;
+ } catch (IllegalArgumentException ise) {}
+ }
+ });
+ methodWRList.stream().forEach( m -> {
+ for (int r : good) {
+ try (Scanner sc = new Scanner("10 10 10 10")) {
+ m.accept(sc, r);
+ } catch (Exception x) {
+ failCount++;
+ }
+ }
+ });
+ report("Radix out of range test");
+ }
+
/*
* Test that closing the stream also closes the underlying Scanner.
* The cases of attempting to open streams on a closed Scanner are