src/share/classes/java/lang/Long.java
Print this page
rev 8975 : 8030814: Long.parseUnsignedLong should throwexception on too large input
Summary: Change test for overflow of unsigned long
Reviewed-by: TBD
@@ -63,10 +63,16 @@
* have, 2<sup>63</sup>-1.
*/
@Native public static final long MAX_VALUE = 0x7fffffffffffffffL;
/**
+ * A constant holding the maximum value a 64-bit unsigned long could
+ * have, 2<sup>64</sup>-1.
+ */
+ private static long MAX_UNSIGNED = 0xffffffffffffffffL;
+
+ /**
* The {@code Class} instance representing the primitive type
* {@code long}.
*
* @since JDK1.1
*/
@@ -629,10 +635,25 @@
*/
public static long parseLong(String s) throws NumberFormatException {
return parseLong(s, 10);
}
+ private static class ParseUnsignedCache {
+ private ParseUnsignedCache(){}
+
+ static final long[] div = new long[Character.MAX_RADIX];
+ static final long[] rem = new long[Character.MAX_RADIX];
+
+ static {
+ // div[0] and rem[0] are unused.
+ for(int radix = 1; radix < Character.MAX_RADIX; radix++) {
+ div[radix] = divideUnsigned(MAX_UNSIGNED, radix);
+ rem[radix] = remainderUnsigned(MAX_UNSIGNED, radix);
+ }
+ }
+ }
+
/**
* Parses the string argument as an unsigned {@code long} in the
* radix specified by the second argument. An unsigned integer
* maps the values usually associated with negative numbers to
* positive numbers larger than {@code MAX_VALUE}.
@@ -697,12 +718,13 @@
long first = parseLong(s.substring(0, len - 1), radix);
int second = Character.digit(s.charAt(len - 1), radix);
if (second < 0) {
throw new NumberFormatException("Bad digit at end of " + s);
}
- long result = first * radix + second;
- if (compareUnsigned(result, first) < 0) {
+ if (compareUnsigned(first, ParseUnsignedCache.div[radix]) > 0 ||
+ (first == ParseUnsignedCache.div[radix] &&
+ second > ParseUnsignedCache.rem[radix])) {
/*
* The maximum unsigned value, (2^64)-1, takes at
* most one more digit to represent than the
* maximum signed value, (2^63)-1. Therefore,
* parsing (len - 1) digits will be appropriately
@@ -717,11 +739,11 @@
* digit.
*/
throw new NumberFormatException(String.format("String value %s exceeds " +
"range of unsigned long.", s));
}
- return result;
+ return first * radix + second;
}
} else {
throw NumberFormatException.forInputString(s);
}
}