提交 8f53032d 编写于 作者: B bpb

6910473: java.math.BigInteger.bitLength() may return negative "int" on large numbers

8021203: BigInteger.doubleValue/floatValue returns 0.0 instead of Infinity
8021204: Constructor BigInteger(String val, int radix) doesn't detect overflow
8022780: Incorrect BigInteger division because of MutableBigInteger.bitLength() overflow
Summary: Prevent construction of overflowed BigIntegers.
Reviewed-by: bpb, darcy, psandoz
Contributed-by: NDmitry Nadezhin <dmitry.nadezhin@oracle.com>
上级 af982e18
...@@ -97,6 +97,21 @@ import sun.misc.FloatConsts; ...@@ -97,6 +97,21 @@ import sun.misc.FloatConsts;
* {@code NullPointerException} when passed * {@code NullPointerException} when passed
* a null object reference for any input parameter. * a null object reference for any input parameter.
* *
* BigInteger must support values in the range
* -2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive) to
* +2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive)
* and may support values outside of that range.
*
* The range of probable prime values is limited and may be less than
* the full supported positive range of {@code BigInteger}.
* The range must be at least 1 to 2<sup>500000000</sup>.
*
* @implNote
* BigInteger constructors and operations throw {@code ArithmeticException} when
* the result is out of the supported range of
* -2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive) to
* +2<sup>{@code Integer.MAX_VALUE}</sup> (exclusive).
*
* @see BigDecimal * @see BigDecimal
* @author Josh Bloch * @author Josh Bloch
* @author Michael McCloskey * @author Michael McCloskey
...@@ -182,6 +197,18 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -182,6 +197,18 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
*/ */
final static long LONG_MASK = 0xffffffffL; final static long LONG_MASK = 0xffffffffL;
/**
* This constant limits {@code mag.length} of BigIntegers to the supported
* range.
*/
private static final int MAX_MAG_LENGTH = Integer.MAX_VALUE / Integer.SIZE + 1; // (1 << 26)
/**
* Bit lengths larger than this constant can cause overflow in searchLen
* calculation and in BitSieve.singleSearch method.
*/
private static final int PRIME_SEARCH_BIT_LENGTH_LIMIT = 500000000;
/** /**
* The threshold value for using Karatsuba multiplication. If the number * The threshold value for using Karatsuba multiplication. If the number
* of ints in both mag arrays are greater than this number, then * of ints in both mag arrays are greater than this number, then
...@@ -256,6 +283,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -256,6 +283,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
mag = stripLeadingZeroBytes(val); mag = stripLeadingZeroBytes(val);
signum = (mag.length == 0 ? 0 : 1); signum = (mag.length == 0 ? 0 : 1);
} }
if (mag.length >= MAX_MAG_LENGTH) {
checkRange();
}
} }
/** /**
...@@ -275,6 +305,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -275,6 +305,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
mag = trustedStripLeadingZeroInts(val); mag = trustedStripLeadingZeroInts(val);
signum = (mag.length == 0 ? 0 : 1); signum = (mag.length == 0 ? 0 : 1);
} }
if (mag.length >= MAX_MAG_LENGTH) {
checkRange();
}
} }
/** /**
...@@ -306,6 +339,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -306,6 +339,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
throw(new NumberFormatException("signum-magnitude mismatch")); throw(new NumberFormatException("signum-magnitude mismatch"));
this.signum = signum; this.signum = signum;
} }
if (mag.length >= MAX_MAG_LENGTH) {
checkRange();
}
} }
/** /**
...@@ -327,6 +363,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -327,6 +363,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
throw(new NumberFormatException("signum-magnitude mismatch")); throw(new NumberFormatException("signum-magnitude mismatch"));
this.signum = signum; this.signum = signum;
} }
if (mag.length >= MAX_MAG_LENGTH) {
checkRange();
}
} }
/** /**
...@@ -359,17 +398,20 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -359,17 +398,20 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
int sign = 1; int sign = 1;
int index1 = val.lastIndexOf('-'); int index1 = val.lastIndexOf('-');
int index2 = val.lastIndexOf('+'); int index2 = val.lastIndexOf('+');
if ((index1 + index2) <= -1) { if (index1 >= 0) {
// No leading sign character or at most one leading sign character if (index1 != 0 || index2 >= 0) {
if (index1 == 0 || index2 == 0) { throw new NumberFormatException("Illegal embedded sign character");
cursor = 1;
if (len == 1)
throw new NumberFormatException("Zero length BigInteger");
} }
if (index1 == 0)
sign = -1; sign = -1;
} else cursor = 1;
} else if (index2 >= 0) {
if (index2 != 0) {
throw new NumberFormatException("Illegal embedded sign character"); throw new NumberFormatException("Illegal embedded sign character");
}
cursor = 1;
}
if (cursor == len)
throw new NumberFormatException("Zero length BigInteger");
// Skip leading zeros and compute number of digits in magnitude // Skip leading zeros and compute number of digits in magnitude
while (cursor < len && while (cursor < len &&
...@@ -388,8 +430,11 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -388,8 +430,11 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
// Pre-allocate array of expected size. May be too large but can // Pre-allocate array of expected size. May be too large but can
// never be too small. Typically exact. // never be too small. Typically exact.
int numBits = (int)(((numDigits * bitsPerDigit[radix]) >>> 10) + 1); long numBits = ((numDigits * bitsPerDigit[radix]) >>> 10) + 1;
int numWords = (numBits + 31) >>> 5; if (numBits + 31 >= (1L << 32)) {
reportOverflow();
}
int numWords = (int) (numBits + 31) >>> 5;
int[] magnitude = new int[numWords]; int[] magnitude = new int[numWords];
// Process first (potentially short) digit group // Process first (potentially short) digit group
...@@ -413,6 +458,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -413,6 +458,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
} }
// Required for cases where the array was overallocated. // Required for cases where the array was overallocated.
mag = trustedStripLeadingZeroInts(magnitude); mag = trustedStripLeadingZeroInts(magnitude);
if (mag.length >= MAX_MAG_LENGTH) {
checkRange();
}
} }
/* /*
...@@ -439,8 +487,11 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -439,8 +487,11 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
if (len < 10) { if (len < 10) {
numWords = 1; numWords = 1;
} else { } else {
int numBits = (int)(((numDigits * bitsPerDigit[10]) >>> 10) + 1); long numBits = ((numDigits * bitsPerDigit[10]) >>> 10) + 1;
numWords = (numBits + 31) >>> 5; if (numBits + 31 >= (1L << 32)) {
reportOverflow();
}
numWords = (int) (numBits + 31) >>> 5;
} }
int[] magnitude = new int[numWords]; int[] magnitude = new int[numWords];
...@@ -456,6 +507,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -456,6 +507,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
destructiveMulAdd(magnitude, intRadix[10], groupVal); destructiveMulAdd(magnitude, intRadix[10], groupVal);
} }
mag = trustedStripLeadingZeroInts(magnitude); mag = trustedStripLeadingZeroInts(magnitude);
if (mag.length >= MAX_MAG_LENGTH) {
checkRange();
}
} }
// Create an integer with the digits between the two indexes // Create an integer with the digits between the two indexes
...@@ -575,7 +629,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -575,7 +629,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
* this constructor is proportional to the value of this parameter. * this constructor is proportional to the value of this parameter.
* @param rnd source of random bits used to select candidates to be * @param rnd source of random bits used to select candidates to be
* tested for primality. * tested for primality.
* @throws ArithmeticException {@code bitLength < 2}. * @throws ArithmeticException {@code bitLength < 2} or {@code bitLength} is too large.
* @see #bitLength() * @see #bitLength()
*/ */
public BigInteger(int bitLength, int certainty, Random rnd) { public BigInteger(int bitLength, int certainty, Random rnd) {
...@@ -607,7 +661,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -607,7 +661,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
* @param rnd source of random bits used to select candidates to be * @param rnd source of random bits used to select candidates to be
* tested for primality. * tested for primality.
* @return a BigInteger of {@code bitLength} bits that is probably prime * @return a BigInteger of {@code bitLength} bits that is probably prime
* @throws ArithmeticException {@code bitLength < 2}. * @throws ArithmeticException {@code bitLength < 2} or {@code bitLength} is too large.
* @see #bitLength() * @see #bitLength()
* @since 1.4 * @since 1.4
*/ */
...@@ -677,7 +731,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -677,7 +731,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
p.mag[p.mag.length-1] &= 0xfffffffe; p.mag[p.mag.length-1] &= 0xfffffffe;
// Use a sieve length likely to contain the next prime number // Use a sieve length likely to contain the next prime number
int searchLen = (bitLength / 20) * 64; int searchLen = getPrimeSearchLen(bitLength);
BitSieve searchSieve = new BitSieve(p, searchLen); BitSieve searchSieve = new BitSieve(p, searchLen);
BigInteger candidate = searchSieve.retrieve(p, certainty, rnd); BigInteger candidate = searchSieve.retrieve(p, certainty, rnd);
...@@ -701,7 +755,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -701,7 +755,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
* *
* @return the first integer greater than this {@code BigInteger} that * @return the first integer greater than this {@code BigInteger} that
* is probably prime. * is probably prime.
* @throws ArithmeticException {@code this < 0}. * @throws ArithmeticException {@code this < 0} or {@code this} is too large.
* @since 1.5 * @since 1.5
*/ */
public BigInteger nextProbablePrime() { public BigInteger nextProbablePrime() {
...@@ -750,7 +804,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -750,7 +804,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
result = result.subtract(ONE); result = result.subtract(ONE);
// Looking for the next large prime // Looking for the next large prime
int searchLen = (result.bitLength() / 20) * 64; int searchLen = getPrimeSearchLen(result.bitLength());
while (true) { while (true) {
BitSieve searchSieve = new BitSieve(result, searchLen); BitSieve searchSieve = new BitSieve(result, searchLen);
...@@ -762,6 +816,13 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -762,6 +816,13 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
} }
} }
private static int getPrimeSearchLen(int bitLength) {
if (bitLength > PRIME_SEARCH_BIT_LENGTH_LIMIT + 1) {
throw new ArithmeticException("Prime search implementation restriction on bitLength");
}
return bitLength / 20 * 64;
}
/** /**
* Returns {@code true} if this BigInteger is probably prime, * Returns {@code true} if this BigInteger is probably prime,
* {@code false} if it's definitely composite. * {@code false} if it's definitely composite.
...@@ -965,6 +1026,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -965,6 +1026,9 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
BigInteger(int[] magnitude, int signum) { BigInteger(int[] magnitude, int signum) {
this.signum = (magnitude.length == 0 ? 0 : signum); this.signum = (magnitude.length == 0 ? 0 : signum);
this.mag = magnitude; this.mag = magnitude;
if (mag.length >= MAX_MAG_LENGTH) {
checkRange();
}
} }
/** /**
...@@ -974,6 +1038,25 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -974,6 +1038,25 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
private BigInteger(byte[] magnitude, int signum) { private BigInteger(byte[] magnitude, int signum) {
this.signum = (magnitude.length == 0 ? 0 : signum); this.signum = (magnitude.length == 0 ? 0 : signum);
this.mag = stripLeadingZeroBytes(magnitude); this.mag = stripLeadingZeroBytes(magnitude);
if (mag.length >= MAX_MAG_LENGTH) {
checkRange();
}
}
/**
* Throws an {@code ArithmeticException} if the {@code BigInteger} would be
* out of the supported range.
*
* @throws ArithmeticException if {@code this} exceeds the supported range.
*/
private void checkRange() {
if (mag.length > MAX_MAG_LENGTH || mag.length == MAX_MAG_LENGTH && mag[0] < 0) {
reportOverflow();
}
}
private static void reportOverflow() {
throw new ArithmeticException("BigInteger would overflow supported range");
} }
//Static Factory Methods //Static Factory Methods
...@@ -2073,6 +2156,10 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -2073,6 +2156,10 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
// The remaining part can then be exponentiated faster. The // The remaining part can then be exponentiated faster. The
// powers of two will be multiplied back at the end. // powers of two will be multiplied back at the end.
int powersOfTwo = partToSquare.getLowestSetBit(); int powersOfTwo = partToSquare.getLowestSetBit();
long bitsToShift = (long)powersOfTwo * exponent;
if (bitsToShift > Integer.MAX_VALUE) {
reportOverflow();
}
int remainingBits; int remainingBits;
...@@ -2126,11 +2213,10 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -2126,11 +2213,10 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
// Multiply back the powers of two (quickly, by shifting left) // Multiply back the powers of two (quickly, by shifting left)
if (powersOfTwo > 0) { if (powersOfTwo > 0) {
int bitsToShift = powersOfTwo*exponent;
if (bitsToShift + scaleFactor <= 62) { // Fits in long? if (bitsToShift + scaleFactor <= 62) { // Fits in long?
return valueOf((result << bitsToShift) * newSign); return valueOf((result << bitsToShift) * newSign);
} else { } else {
return valueOf(result*newSign).shiftLeft(bitsToShift); return valueOf(result*newSign).shiftLeft((int) bitsToShift);
} }
} }
else { else {
...@@ -2375,8 +2461,17 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -2375,8 +2461,17 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
BigInteger y1 = m2.modInverse(m1); BigInteger y1 = m2.modInverse(m1);
BigInteger y2 = m1.modInverse(m2); BigInteger y2 = m1.modInverse(m2);
result = a1.multiply(m2).multiply(y1).add if (m.mag.length < MAX_MAG_LENGTH / 2) {
(a2.multiply(m1).multiply(y2)).mod(m); result = a1.multiply(m2).multiply(y1).add(a2.multiply(m1).multiply(y2)).mod(m);
} else {
MutableBigInteger t1 = new MutableBigInteger();
new MutableBigInteger(a1.multiply(m2)).multiply(new MutableBigInteger(y1), t1);
MutableBigInteger t2 = new MutableBigInteger();
new MutableBigInteger(a2.multiply(m1)).multiply(new MutableBigInteger(y2), t2);
t1.add(t2);
MutableBigInteger q = new MutableBigInteger();
result = t1.divide(new MutableBigInteger(m), q).toBigInteger();
}
} }
return (invertResult ? result.modInverse(m) : result); return (invertResult ? result.modInverse(m) : result);
...@@ -2797,27 +2892,31 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -2797,27 +2892,31 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
* *
* @param n shift distance, in bits. * @param n shift distance, in bits.
* @return {@code this << n} * @return {@code this << n}
* @throws ArithmeticException if the shift distance is {@code
* Integer.MIN_VALUE}.
* @see #shiftRight * @see #shiftRight
*/ */
public BigInteger shiftLeft(int n) { public BigInteger shiftLeft(int n) {
if (signum == 0) if (signum == 0)
return ZERO; return ZERO;
if (n == 0) if (n > 0) {
return new BigInteger(shiftLeft(mag, n), signum);
} else if (n == 0) {
return this; return this;
if (n < 0) {
if (n == Integer.MIN_VALUE) {
throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
} else { } else {
return shiftRight(-n); // Possible int overflow in (-n) is not a trouble,
} // because shiftRightImpl considers its argument unsigned
return shiftRightImpl(-n);
} }
int[] newMag = shiftLeft(mag, n);
return new BigInteger(newMag, signum);
} }
/**
* Returns a magnitude array whose value is {@code (mag << n)}.
* The shift distance, {@code n}, is considered unnsigned.
* (Computes <tt>this * 2<sup>n</sup></tt>.)
*
* @param mag magnitude, the most-significant int ({@code mag[0]}) must be non-zero.
* @param n unsigned shift distance, in bits.
* @return {@code mag << n}
*/
private static int[] shiftLeft(int[] mag, int n) { private static int[] shiftLeft(int[] mag, int n) {
int nInts = n >>> 5; int nInts = n >>> 5;
int nBits = n & 0x1f; int nBits = n & 0x1f;
...@@ -2853,21 +2952,31 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -2853,21 +2952,31 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
* *
* @param n shift distance, in bits. * @param n shift distance, in bits.
* @return {@code this >> n} * @return {@code this >> n}
* @throws ArithmeticException if the shift distance is {@code
* Integer.MIN_VALUE}.
* @see #shiftLeft * @see #shiftLeft
*/ */
public BigInteger shiftRight(int n) { public BigInteger shiftRight(int n) {
if (n == 0) if (signum == 0)
return ZERO;
if (n > 0) {
return shiftRightImpl(n);
} else if (n == 0) {
return this; return this;
if (n < 0) {
if (n == Integer.MIN_VALUE) {
throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
} else { } else {
return shiftLeft(-n); // Possible int overflow in {@code -n} is not a trouble,
// because shiftLeft considers its argument unsigned
return new BigInteger(shiftLeft(mag, -n), signum);
} }
} }
/**
* Returns a BigInteger whose value is {@code (this >> n)}. The shift
* distance, {@code n}, is considered unsigned.
* (Computes <tt>floor(this * 2<sup>-n</sup>)</tt>.)
*
* @param n unsigned shift distance, in bits.
* @return {@code this >> n}
*/
private BigInteger shiftRightImpl(int n) {
int nInts = n >>> 5; int nInts = n >>> 5;
int nBits = n & 0x1f; int nBits = n & 0x1f;
int magLen = mag.length; int magLen = mag.length;
...@@ -3899,7 +4008,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -3899,7 +4008,7 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
; ;
int extraByte = (k == byteLength) ? 1 : 0; int extraByte = (k == byteLength) ? 1 : 0;
int intLength = ((byteLength - keep + extraByte) + 3)/4; int intLength = ((byteLength - keep + extraByte) + 3) >>> 2;
int result[] = new int[intLength]; int result[] = new int[intLength];
/* Copy one's complement of input into output, leaving extra /* Copy one's complement of input into output, leaving extra
...@@ -4135,7 +4244,8 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -4135,7 +4244,8 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
message = "BigInteger: Signum not present in stream"; message = "BigInteger: Signum not present in stream";
throw new java.io.StreamCorruptedException(message); throw new java.io.StreamCorruptedException(message);
} }
if ((magnitude.length == 0) != (sign == 0)) { int[] mag = stripLeadingZeroBytes(magnitude);
if ((mag.length == 0) != (sign == 0)) {
String message = "BigInteger: signum-magnitude mismatch"; String message = "BigInteger: signum-magnitude mismatch";
if (fields.defaulted("magnitude")) if (fields.defaulted("magnitude"))
message = "BigInteger: Magnitude not present in stream"; message = "BigInteger: Magnitude not present in stream";
...@@ -4146,7 +4256,14 @@ public class BigInteger extends Number implements Comparable<BigInteger> { ...@@ -4146,7 +4256,14 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
UnsafeHolder.putSign(this, sign); UnsafeHolder.putSign(this, sign);
// Calculate mag field from magnitude and discard magnitude // Calculate mag field from magnitude and discard magnitude
UnsafeHolder.putMag(this, stripLeadingZeroBytes(magnitude)); UnsafeHolder.putMag(this, mag);
if (mag.length >= MAX_MAG_LENGTH) {
try {
checkRange();
} catch (ArithmeticException e) {
throw new java.io.StreamCorruptedException("BigInteger: Out of the supported range");
}
}
} }
// Support for resetting final fields while deserializing // Support for resetting final fields while deserializing
......
...@@ -1257,14 +1257,14 @@ class MutableBigInteger { ...@@ -1257,14 +1257,14 @@ class MutableBigInteger {
int j = (s+m-1) / m; // step 2a: j = ceil(s/m) int j = (s+m-1) / m; // step 2a: j = ceil(s/m)
int n = j * m; // step 2b: block length in 32-bit units int n = j * m; // step 2b: block length in 32-bit units
int n32 = 32 * n; // block length in bits long n32 = 32L * n; // block length in bits
int sigma = Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n} int sigma = (int) Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n}
MutableBigInteger bShifted = new MutableBigInteger(b); MutableBigInteger bShifted = new MutableBigInteger(b);
bShifted.safeLeftShift(sigma); // step 4a: shift b so its length is a multiple of n bShifted.safeLeftShift(sigma); // step 4a: shift b so its length is a multiple of n
safeLeftShift(sigma); // step 4b: shift this by the same amount safeLeftShift(sigma); // step 4b: shift this by the same amount
// step 5: t is the number of blocks needed to accommodate this plus one additional bit // step 5: t is the number of blocks needed to accommodate this plus one additional bit
int t = (bitLength()+n32) / n32; int t = (int) ((bitLength()+n32) / n32);
if (t < 2) { if (t < 2) {
t = 2; t = 2;
} }
...@@ -1421,10 +1421,10 @@ class MutableBigInteger { ...@@ -1421,10 +1421,10 @@ class MutableBigInteger {
} }
/** @see BigInteger#bitLength() */ /** @see BigInteger#bitLength() */
int bitLength() { long bitLength() {
if (intLen == 0) if (intLen == 0)
return 0; return 0;
return intLen*32 - Integer.numberOfLeadingZeros(value[offset]); return intLen*32L - Integer.numberOfLeadingZeros(value[offset]);
} }
/** /**
......
/*
* Copyright (c) 2013, 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 6910473
* @summary Test that bitLength() is not negative
* @author Dmitry Nadezhin
*/
import java.math.BigInteger;
public class BitLengthOverflow {
public static void main(String[] args) {
try {
BigInteger x = BigInteger.ONE.shiftLeft(Integer.MAX_VALUE); // x = pow(2,Integer.MAX_VALUE)
if (x.bitLength() != (1L << 31))
throw new RuntimeException("Incorrect bitLength() " + x.bitLength());
System.out.println("Surprisingly passed with correct bitLength() " + x.bitLength());
} catch (ArithmeticException e) {
// expected
System.out.println("Overflow is reported by ArithmeticException, as expected");
} catch (OutOfMemoryError e) {
// possible
System.out.println("OutOfMemoryError");
}
}
}
/*
* Copyright (c) 2011, 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 8022780
* @summary Test division of large values
* @author Dmitry Nadezhin
*/
import java.math.BigInteger;
public class DivisionOverflow {
public static void main(String[] args) {
try {
BigInteger a = BigInteger.ONE.shiftLeft(2147483646);
BigInteger b = BigInteger.ONE.shiftLeft(1568);
BigInteger[] qr = a.divideAndRemainder(b);
BigInteger q = qr[0];
BigInteger r = qr[1];
if (!r.equals(BigInteger.ZERO))
throw new RuntimeException("Incorrect singum() of remainder " + r.signum());
if (q.bitLength() != 2147482079)
throw new RuntimeException("Incorrect bitLength() of quotient " + q.bitLength());
System.out.println("Division of large values passed without overflow.");
} catch (OutOfMemoryError e) {
// possible
System.out.println("OutOfMemoryError");
}
}
}
/*
* Copyright (c) 2013, 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 8021203
* @summary Test that doubleValue() doesn't overflow
* @author Dmitry Nadezhin
*/
import java.math.BigInteger;
public class DoubleValueOverflow {
public static void main(String[] args) {
try {
BigInteger x = BigInteger.valueOf(2).shiftLeft(Integer.MAX_VALUE); // x = pow(2,pow(2,31))
if (x.doubleValue() != Double.POSITIVE_INFINITY)
throw new RuntimeException("Incorrect doubleValue() " + x.doubleValue());
System.out.println("Passed with correct result");
} catch (ArithmeticException e) {
// expected
System.out.println("Overflow is reported by ArithmeticException, as expected");
} catch (OutOfMemoryError e) {
// possible
System.out.println("OutOfMemoryError");
}
}
}
...@@ -27,22 +27,41 @@ ...@@ -27,22 +27,41 @@
* @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE * @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE
* @author Joseph D. Darcy * @author Joseph D. Darcy
*/ */
import java.math.BigInteger;
import static java.math.BigInteger.*; import static java.math.BigInteger.*;
public class ExtremeShiftingTests { public class ExtremeShiftingTests {
public static void main(String... args) { public static void main(String... args) {
BigInteger bi = ONE.shiftLeft(Integer.MIN_VALUE);
if (!bi.equals(ZERO))
throw new RuntimeException("1 << " + Integer.MIN_VALUE);
bi = ZERO.shiftLeft(Integer.MIN_VALUE);
if (!bi.equals(ZERO))
throw new RuntimeException("0 << " + Integer.MIN_VALUE);
bi = BigInteger.valueOf(-1);
bi = bi.shiftLeft(Integer.MIN_VALUE);
if (!bi.equals(BigInteger.valueOf(-1)))
throw new RuntimeException("-1 << " + Integer.MIN_VALUE);
try { try {
ONE.shiftLeft(Integer.MIN_VALUE); ONE.shiftRight(Integer.MIN_VALUE);
throw new RuntimeException("Should not reach here."); throw new RuntimeException("1 >> " + Integer.MIN_VALUE);
} catch (ArithmeticException ae) { } catch (ArithmeticException ae) {
; // Expected ; // Expected
} }
bi = ZERO.shiftRight(Integer.MIN_VALUE);
if (!bi.equals(ZERO))
throw new RuntimeException("0 >> " + Integer.MIN_VALUE);
try { try {
ONE.shiftRight(Integer.MIN_VALUE); BigInteger.valueOf(-1).shiftRight(Integer.MIN_VALUE);
throw new RuntimeException("Should not reach here."); throw new RuntimeException("-1 >> " + Integer.MIN_VALUE);
} catch (ArithmeticException ae) { } catch (ArithmeticException ae) {
; // Expected ; // Expected
} }
} }
} }
/*
* Copyright (c) 2013, 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 8021204
* @summary Test constructor BigInteger(String val, int radix) on very long string
* @author Dmitry Nadezhin
*/
import java.math.BigInteger;
public class StringConstructorOverflow {
// String with hexadecimal value pow(2,pow(2,34))+1
private static String makeLongHexString() {
StringBuilder sb = new StringBuilder();
sb.append('1');
for (int i = 0; i < (1 << 30) - 1; i++) {
sb.append('0');
}
sb.append('1');
return sb.toString();
}
public static void main(String[] args) {
try {
BigInteger bi = new BigInteger(makeLongHexString(), 16);
if (bi.compareTo(BigInteger.ONE) <= 0)
throw new RuntimeException("Incorrect result " + bi.toString());
} catch (ArithmeticException e) {
// expected
System.out.println("Overflow is reported by ArithmeticException, as expected");
} catch (OutOfMemoryError e) {
// possible
System.out.println("OutOfMemoryError");
System.out.println("Run jtreg with -javaoption:-Xmx8g");
}
}
}
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册