# HG changeset patch # User bpb # Date 1383180312 25200 # Node ID 0734e1584d9db2b886424336852ace4dea1dffa0 # Parent e8894e3224d91a1995bb4e1bc1a5f0f0918cfdba 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: Dmitry Nadezhin diff -r e8894e3224d9 -r 0734e1584d9d src/share/classes/java/math/BigInteger.java --- a/src/share/classes/java/math/BigInteger.java Wed Oct 30 17:27:25 2013 -0700 +++ b/src/share/classes/java/math/BigInteger.java Wed Oct 30 17:45:12 2013 -0700 @@ -97,6 +97,21 @@ * {@code NullPointerException} when passed * a null object reference for any input parameter. * + * BigInteger must support values in the range + * -2{@code Integer.MAX_VALUE} (exclusive) to + * +2{@code Integer.MAX_VALUE} (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 2500000000. + * + * @implNote + * BigInteger constructors and operations throw {@code ArithmeticException} when + * the result is out of the supported range of + * -2{@code Integer.MAX_VALUE} (exclusive) to + * +2{@code Integer.MAX_VALUE} (exclusive). + * * @see BigDecimal * @author Josh Bloch * @author Michael McCloskey @@ -183,6 +198,18 @@ 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 * of ints in both mag arrays are greater than this number, then * Karatsuba multiplication will be used. This value is found @@ -256,6 +283,9 @@ mag = stripLeadingZeroBytes(val); signum = (mag.length == 0 ? 0 : 1); } + if (mag.length >= MAX_MAG_LENGTH) { + checkRange(); + } } /** @@ -275,6 +305,9 @@ mag = trustedStripLeadingZeroInts(val); signum = (mag.length == 0 ? 0 : 1); } + if (mag.length >= MAX_MAG_LENGTH) { + checkRange(); + } } /** @@ -306,6 +339,9 @@ throw(new NumberFormatException("signum-magnitude mismatch")); this.signum = signum; } + if (mag.length >= MAX_MAG_LENGTH) { + checkRange(); + } } /** @@ -327,6 +363,9 @@ throw(new NumberFormatException("signum-magnitude mismatch")); this.signum = signum; } + if (mag.length >= MAX_MAG_LENGTH) { + checkRange(); + } } /** @@ -359,17 +398,20 @@ int sign = 1; int index1 = val.lastIndexOf('-'); int index2 = val.lastIndexOf('+'); - if ((index1 + index2) <= -1) { - // No leading sign character or at most one leading sign character - if (index1 == 0 || index2 == 0) { - cursor = 1; - if (len == 1) - throw new NumberFormatException("Zero length BigInteger"); + if (index1 >= 0) { + if (index1 != 0 || index2 >= 0) { + throw new NumberFormatException("Illegal embedded sign character"); } - if (index1 == 0) - sign = -1; - } else - throw new NumberFormatException("Illegal embedded sign character"); + sign = -1; + cursor = 1; + } else if (index2 >= 0) { + if (index2 != 0) { + 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 while (cursor < len && @@ -388,8 +430,11 @@ // Pre-allocate array of expected size. May be too large but can // never be too small. Typically exact. - int numBits = (int)(((numDigits * bitsPerDigit[radix]) >>> 10) + 1); - int numWords = (numBits + 31) >>> 5; + long numBits = ((numDigits * bitsPerDigit[radix]) >>> 10) + 1; + if (numBits + 31 >= (1L << 32)) { + reportOverflow(); + } + int numWords = (int) (numBits + 31) >>> 5; int[] magnitude = new int[numWords]; // Process first (potentially short) digit group @@ -413,6 +458,9 @@ } // Required for cases where the array was overallocated. mag = trustedStripLeadingZeroInts(magnitude); + if (mag.length >= MAX_MAG_LENGTH) { + checkRange(); + } } /* @@ -439,8 +487,11 @@ if (len < 10) { numWords = 1; } else { - int numBits = (int)(((numDigits * bitsPerDigit[10]) >>> 10) + 1); - numWords = (numBits + 31) >>> 5; + long numBits = ((numDigits * bitsPerDigit[10]) >>> 10) + 1; + if (numBits + 31 >= (1L << 32)) { + reportOverflow(); + } + numWords = (int) (numBits + 31) >>> 5; } int[] magnitude = new int[numWords]; @@ -456,6 +507,9 @@ destructiveMulAdd(magnitude, intRadix[10], groupVal); } mag = trustedStripLeadingZeroInts(magnitude); + if (mag.length >= MAX_MAG_LENGTH) { + checkRange(); + } } // Create an integer with the digits between the two indexes @@ -575,7 +629,7 @@ * this constructor is proportional to the value of this parameter. * @param rnd source of random bits used to select candidates to be * tested for primality. - * @throws ArithmeticException {@code bitLength < 2}. + * @throws ArithmeticException {@code bitLength < 2} or {@code bitLength} is too large. * @see #bitLength() */ public BigInteger(int bitLength, int certainty, Random rnd) { @@ -607,7 +661,7 @@ * @param rnd source of random bits used to select candidates to be * tested for primality. * @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() * @since 1.4 */ @@ -677,7 +731,7 @@ p.mag[p.mag.length-1] &= 0xfffffffe; // 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); BigInteger candidate = searchSieve.retrieve(p, certainty, rnd); @@ -701,7 +755,7 @@ * * @return the first integer greater than this {@code BigInteger} that * is probably prime. - * @throws ArithmeticException {@code this < 0}. + * @throws ArithmeticException {@code this < 0} or {@code this} is too large. * @since 1.5 */ public BigInteger nextProbablePrime() { @@ -750,7 +804,7 @@ result = result.subtract(ONE); // Looking for the next large prime - int searchLen = (result.bitLength() / 20) * 64; + int searchLen = getPrimeSearchLen(result.bitLength()); while (true) { BitSieve searchSieve = new BitSieve(result, searchLen); @@ -762,6 +816,13 @@ } } + 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, * {@code false} if it's definitely composite. @@ -965,6 +1026,9 @@ BigInteger(int[] magnitude, int signum) { this.signum = (magnitude.length == 0 ? 0 : signum); this.mag = magnitude; + if (mag.length >= MAX_MAG_LENGTH) { + checkRange(); + } } /** @@ -974,6 +1038,25 @@ private BigInteger(byte[] magnitude, int signum) { this.signum = (magnitude.length == 0 ? 0 : signum); 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 @@ -2073,6 +2156,10 @@ // The remaining part can then be exponentiated faster. The // powers of two will be multiplied back at the end. int powersOfTwo = partToSquare.getLowestSetBit(); + long bitsToShift = (long)powersOfTwo * exponent; + if (bitsToShift > Integer.MAX_VALUE) { + reportOverflow(); + } int remainingBits; @@ -2126,11 +2213,10 @@ // Multiply back the powers of two (quickly, by shifting left) if (powersOfTwo > 0) { - int bitsToShift = powersOfTwo*exponent; if (bitsToShift + scaleFactor <= 62) { // Fits in long? return valueOf((result << bitsToShift) * newSign); } else { - return valueOf(result*newSign).shiftLeft(bitsToShift); + return valueOf(result*newSign).shiftLeft((int) bitsToShift); } } else { @@ -2375,8 +2461,17 @@ BigInteger y1 = m2.modInverse(m1); BigInteger y2 = m1.modInverse(m2); - result = a1.multiply(m2).multiply(y1).add - (a2.multiply(m1).multiply(y2)).mod(m); + if (m.mag.length < MAX_MAG_LENGTH / 2) { + 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); @@ -2797,27 +2892,31 @@ * * @param n shift distance, in bits. * @return {@code this << n} - * @throws ArithmeticException if the shift distance is {@code - * Integer.MIN_VALUE}. * @see #shiftRight */ public BigInteger shiftLeft(int n) { if (signum == 0) return ZERO; - if (n == 0) + if (n > 0) { + return new BigInteger(shiftLeft(mag, n), signum); + } else if (n == 0) { return this; - if (n < 0) { - if (n == Integer.MIN_VALUE) { - throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported."); - } else { - return shiftRight(-n); - } + } else { + // 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 this * 2n.) + * + * @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) { int nInts = n >>> 5; int nBits = n & 0x1f; @@ -2853,21 +2952,31 @@ * * @param n shift distance, in bits. * @return {@code this >> n} - * @throws ArithmeticException if the shift distance is {@code - * Integer.MIN_VALUE}. * @see #shiftLeft */ 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; - if (n < 0) { - if (n == Integer.MIN_VALUE) { - throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported."); - } else { - return shiftLeft(-n); - } + } else { + // 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 floor(this * 2-n).) + * + * @param n unsigned shift distance, in bits. + * @return {@code this >> n} + */ + private BigInteger shiftRightImpl(int n) { int nInts = n >>> 5; int nBits = n & 0x1f; int magLen = mag.length; @@ -3899,7 +4008,7 @@ ; 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]; /* Copy one's complement of input into output, leaving extra @@ -4135,7 +4244,8 @@ message = "BigInteger: Signum not present in stream"; 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"; if (fields.defaulted("magnitude")) message = "BigInteger: Magnitude not present in stream"; @@ -4146,7 +4256,14 @@ UnsafeHolder.putSign(this, sign); // 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 diff -r e8894e3224d9 -r 0734e1584d9d src/share/classes/java/math/MutableBigInteger.java --- a/src/share/classes/java/math/MutableBigInteger.java Wed Oct 30 17:27:25 2013 -0700 +++ b/src/share/classes/java/math/MutableBigInteger.java Wed Oct 30 17:45:12 2013 -0700 @@ -1257,14 +1257,14 @@ 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 n32 = 32 * n; // block length in bits - int sigma = Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n} + long n32 = 32L * n; // block length in bits + int sigma = (int) Math.max(0, n32 - b.bitLength()); // step 3: sigma = max{T | (2^T)*B < beta^n} MutableBigInteger bShifted = new MutableBigInteger(b); 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 // 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) { t = 2; } @@ -1421,10 +1421,10 @@ } /** @see BigInteger#bitLength() */ - int bitLength() { + long bitLength() { if (intLen == 0) return 0; - return intLen*32 - Integer.numberOfLeadingZeros(value[offset]); + return intLen*32L - Integer.numberOfLeadingZeros(value[offset]); } /** diff -r e8894e3224d9 -r 0734e1584d9d test/java/math/BigInteger/BitLengthOverflow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/math/BigInteger/BitLengthOverflow.java Wed Oct 30 17:45:12 2013 -0700 @@ -0,0 +1,49 @@ +/* + * 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"); + } + } +} diff -r e8894e3224d9 -r 0734e1584d9d test/java/math/BigInteger/DivisionOverflow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/math/BigInteger/DivisionOverflow.java Wed Oct 30 17:45:12 2013 -0700 @@ -0,0 +1,51 @@ +/* + * 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"); + } + } +} diff -r e8894e3224d9 -r 0734e1584d9d test/java/math/BigInteger/DoubleValueOverflow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/math/BigInteger/DoubleValueOverflow.java Wed Oct 30 17:45:12 2013 -0700 @@ -0,0 +1,49 @@ +/* + * 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"); + } + } +} diff -r e8894e3224d9 -r 0734e1584d9d test/java/math/BigInteger/ExtremeShiftingTests.java --- a/test/java/math/BigInteger/ExtremeShiftingTests.java Wed Oct 30 17:27:25 2013 -0700 +++ b/test/java/math/BigInteger/ExtremeShiftingTests.java Wed Oct 30 17:45:12 2013 -0700 @@ -27,22 +27,41 @@ * @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE * @author Joseph D. Darcy */ +import java.math.BigInteger; import static java.math.BigInteger.*; public class ExtremeShiftingTests { 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 { - ONE.shiftLeft(Integer.MIN_VALUE); - throw new RuntimeException("Should not reach here."); + ONE.shiftRight(Integer.MIN_VALUE); + throw new RuntimeException("1 >> " + Integer.MIN_VALUE); } catch (ArithmeticException ae) { ; // Expected } + bi = ZERO.shiftRight(Integer.MIN_VALUE); + if (!bi.equals(ZERO)) + throw new RuntimeException("0 >> " + Integer.MIN_VALUE); + try { - ONE.shiftRight(Integer.MIN_VALUE); - throw new RuntimeException("Should not reach here."); + BigInteger.valueOf(-1).shiftRight(Integer.MIN_VALUE); + throw new RuntimeException("-1 >> " + Integer.MIN_VALUE); } catch (ArithmeticException ae) { ; // Expected } + } } diff -r e8894e3224d9 -r 0734e1584d9d test/java/math/BigInteger/StringConstructorOverflow.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/math/BigInteger/StringConstructorOverflow.java Wed Oct 30 17:45:12 2013 -0700 @@ -0,0 +1,59 @@ +/* + * 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"); + } + } +} diff -r e8894e3224d9 -r 0734e1584d9d test/java/math/BigInteger/SymmetricRangeTests.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/math/BigInteger/SymmetricRangeTests.java Wed Oct 30 17:45:12 2013 -0700 @@ -0,0 +1,662 @@ +/* + * 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. + */ + +/* + * This test is intentionally ignored because of huge memory requirements + * @ test + * @run main/timeout=180/othervm -Xmx8g SymmetricRangeTests + * @bug 6910473 8021204 8021203 9005933 + * @summary Test range of BigInteger values + * @author Dmitry Nadezhin + */ +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Arrays; +import java.util.Random; +import java.math.BigInteger; + +public class SymmetricRangeTests { + + private static final BigInteger MAX_VALUE = makeMaxValue(); + private static final BigInteger MIN_VALUE = MAX_VALUE.negate(); + + private static BigInteger makeMaxValue() { + byte[] ba = new byte[1 << 28]; + Arrays.fill(ba, (byte) 0xFF); + ba[0] = (byte) 0x7F; + return new BigInteger(ba); + } + + private static void check(String msg, BigInteger actual, BigInteger expected) { + if (!actual.equals(expected)) { + throw new RuntimeException(msg + ".bitLength()=" + actual.bitLength()); + } + } + + private static void check(String msg, double actual, double expected) { + if (actual != expected) { + throw new RuntimeException(msg + "=" + actual); + } + } + + private static void check(String msg, float actual, float expected) { + if (actual != expected) { + throw new RuntimeException(msg + "=" + actual); + } + } + + private static void check(String msg, long actual, long expected) { + if (actual != expected) { + throw new RuntimeException(msg + "=" + actual); + } + } + + private static void check(String msg, int actual, int expected) { + if (actual != expected) { + throw new RuntimeException(msg + "=" + actual); + } + } + + private static void testOverflowInMakePositive() { + System.out.println("Testing overflow in BigInteger.makePositive"); + byte[] ba = new byte[Integer.MAX_VALUE - 2]; + ba[0] = (byte) 0x80; + try { + BigInteger actual = new BigInteger(ba); + throw new RuntimeException("new BigInteger(ba).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testBug8021204() { + System.out.println("Testing Bug 8021204"); + StringBuilder sb = new StringBuilder(); + sb.append('1'); + for (int i = 0; i < (1 << 30) - 1; i++) { + sb.append('0'); + } + sb.append('1'); + String s = sb.toString(); + sb = null; + try { + BigInteger actual = new BigInteger(s, 16); + throw new RuntimeException("new BigInteger(\"1000...001\").bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testOverflowInBitSieve() { + System.out.println("Testing overflow in BitSieve.sieveSingle"); + int bitLength = (5 << 27) - 1; + try { + Random rnd = new Random(); + BigInteger actual = new BigInteger(bitLength, 0, rnd); + throw new RuntimeException("new BigInteger(bitLength, 0, null).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + try { + BigInteger bi = BigInteger.ONE.shiftLeft(bitLength - 1).subtract(BigInteger.ONE); + BigInteger actual = bi.nextProbablePrime(); + throw new RuntimeException("bi.nextActualPrime().bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testAdd() { + System.out.println("Testing BigInteger.add"); + try { + BigInteger actual = MAX_VALUE.add(BigInteger.ONE); + throw new RuntimeException("BigInteger.MAX_VALUE.add(BigInteger.ONE).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testSubtract() { + System.out.println("Testing BigInteger.subtract"); + try { + BigInteger actual = MIN_VALUE.subtract(BigInteger.ONE); + throw new RuntimeException("BigInteger.MIN_VALUE.subtract(BigInteger.ONE).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testMultiply() { + System.out.println("Testing BigInteger.multiply"); + int py = 2000; + int px = Integer.MAX_VALUE - py; + BigInteger x = BigInteger.ONE.shiftLeft(px); + BigInteger y = BigInteger.ONE.shiftLeft(py); + try { + BigInteger actual = x.multiply(y); + throw new RuntimeException("(1 << " + px + " ) * (1 << " + py + ").bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testDivide() { + System.out.println("Testing BigInteger.divide"); + check("BigInteger.MIN_VALUE.divide(BigInteger.valueOf(-1))", + MIN_VALUE.divide(BigInteger.valueOf(-1)), MAX_VALUE); + check("BigInteger.MIN_VALUE.divide(BigInteger.ONE)", + MIN_VALUE.divide(BigInteger.ONE), MIN_VALUE); + } + + private static void testDivideAndRemainder(String msg, BigInteger dividend, BigInteger divisor, + BigInteger expectedQuotent, BigInteger expectedRemainder) { + BigInteger[] qr = dividend.divideAndRemainder(divisor); + check(msg + "[0]", qr[0], expectedQuotent); + check(msg + "[1]", qr[1], expectedRemainder); + } + + private static void testDivideAndRemainder() { + System.out.println("Testing BigInteger.divideAndRemainder"); + testDivideAndRemainder("BigInteger.MIN_VALUE.divideAndRemainder(BigInteger.valueOf(-1))", + MIN_VALUE, BigInteger.valueOf(-1), + MAX_VALUE, + BigInteger.ZERO); + } + + private static void testBug9005933() { + System.out.println("Testing Bug 9005933"); + int dividendPow = 2147483646; + int divisorPow = 1568; + BigInteger dividend = BigInteger.ONE.shiftLeft(dividendPow); + BigInteger divisor = BigInteger.ONE.shiftLeft(divisorPow); + testDivideAndRemainder("(1 << " + dividendPow + ").divideAndRemainder(1 << " + divisorPow + ")", + dividend, divisor, + BigInteger.ONE.shiftLeft(dividendPow - divisorPow), + BigInteger.ZERO); + } + + private static void testRemainder() { + System.out.println("Testing BigInteger.remainder"); + check("BigInteger.MIN_VALUE.remainder(BigInteger.valueOf(-1))", + MIN_VALUE.remainder(BigInteger.valueOf(-1)), BigInteger.ZERO); + } + + private static void testPow() { + System.out.println("Testing BigInteger.pow"); + check("BigInteger.MIN_VALUE.pow(1)", + MIN_VALUE.pow(1), MIN_VALUE); + try { + BigInteger actual = BigInteger.valueOf(4).pow(Integer.MAX_VALUE); + throw new RuntimeException("BigInteger.valueOf(4).pow(Integer.MAX_VALUE).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testGcd() { + System.out.println("Testing BigInteger.gcd"); + check("BigInteger.MIN_VALUE.gcd(BigInteger.MIN_VALUE)", + MIN_VALUE.gcd(MIN_VALUE), MAX_VALUE); + check("BigInteger.MIN_VALUE.gcd(BigInteger.ZERO)", + MIN_VALUE.gcd(BigInteger.ZERO), MAX_VALUE); + check("BigInteger.ZERO.gcd(MIN_VALUE)", + BigInteger.ZERO.gcd(MIN_VALUE), MAX_VALUE); + } + + private static void testAbs() { + System.out.println("Testing BigInteger.abs"); + check("BigInteger.MIN_VALUE.abs()", + MIN_VALUE.abs(), MAX_VALUE); + check("BigInteger.MAX_VALUE.abs()", + MAX_VALUE.abs(), MAX_VALUE); + } + + private static void testNegate() { + System.out.println("Testing BigInteger.negate"); + check("BigInteger.MIN_VALUE.negate()", + MIN_VALUE.negate(), MAX_VALUE); + check("BigInteger.MAX_VALUE.negate()", + MAX_VALUE.negate(), MIN_VALUE); + } + + private static void testMod() { + System.out.println("Testing BigInteger.mod"); + check("BigInteger.MIN_VALUE.mod(BigInteger.MAX_VALUE)", + MIN_VALUE.mod(MAX_VALUE), BigInteger.ZERO); + check("BigInteger.MAX_VALUE.mod(BigInteger.MAX_VALUE)", + MIN_VALUE.mod(MAX_VALUE), BigInteger.ZERO); + } + + private static void testModPow() { + System.out.println("Testing BigInteger.modPow"); + BigInteger x = BigInteger.valueOf(3); + BigInteger m = BigInteger.valueOf(-4).subtract(MIN_VALUE); + check("BigInteger.valueOf(3).modPow(BigInteger.ONE, m)", + x.modPow(BigInteger.ONE, m), x); + } + + // slow test + private static void testModInverse() { + System.out.println("Testing BigInteger.modInverse"); + check("BigInteger.MIN_VALUE.modInverse(BigInteger.MAX_VALUE)", + MIN_VALUE.modInverse(MAX_VALUE), MAX_VALUE.subtract(BigInteger.ONE)); + } + + private static void testShiftLeft() { + System.out.println("Testing BigInteger.shiftLeft"); + try { + BigInteger actual = MIN_VALUE.shiftLeft(1); + throw new RuntimeException("BigInteger.MIN_VALUE.shiftLeft(1).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + try { + BigInteger actual = MAX_VALUE.shiftLeft(1); + throw new RuntimeException("BigInteger.MAX_VALUE.shiftLeft(1).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testShiftRight() { + System.out.println("Testing BigInteger.shiftRight"); + try { + BigInteger actual = MIN_VALUE.shiftRight(-1); + throw new RuntimeException("BigInteger.MIN_VALUE.shiftRight(-1).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + try { + BigInteger actual = MAX_VALUE.shiftRight(-1); + throw new RuntimeException("BigInteger.MAX_VALUE.shiftRight(-1).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testAnd() { + System.out.println("Testing BigInteger.and"); + check("BigInteger.MIN_VALUE.and(BigInteger.MIN_VALUE)", + MIN_VALUE.and(MIN_VALUE), MIN_VALUE); + check("BigInteger.MAX_VALUE.and(BigInteger.MAX_VALUE)", + MAX_VALUE.and(MAX_VALUE), MAX_VALUE); + check("BigInteger.MIN_VALUE.and(BigInteger.MAX_VALUE)", + MIN_VALUE.and(MAX_VALUE), BigInteger.ONE); + try { + BigInteger actual = MIN_VALUE.and(BigInteger.valueOf(-2)); + throw new RuntimeException("BigInteger.MIN_VALUE.and(-2)).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testOr() { + System.out.println("Testing BigInteger.or"); + check("BigInteger.MIN_VALUE.or(BigInteger.MIN_VALUE)", + MIN_VALUE.or(MIN_VALUE), MIN_VALUE); + check("BigInteger.MAX_VALUE.or(BigInteger.MAX_VALUE)", + MAX_VALUE.or(MAX_VALUE), MAX_VALUE); + check("BigInteger.MIN_VALUE.and(BigInteger.MAX_VALUE)", + MIN_VALUE.or(MAX_VALUE), BigInteger.valueOf(-1)); + } + + private static void testXor() { + System.out.println("Testing BigInteger.xor"); + check("BigInteger.MIN_VALUE.xor(BigInteger.MIN_VALUE)", + MIN_VALUE.xor(MIN_VALUE), BigInteger.ZERO); + check("BigInteger.MAX_VALUE.xor(BigInteger.MAX_VALUE)", + MAX_VALUE.xor(MAX_VALUE), BigInteger.ZERO); + check("BigInteger.MIN_VALUE.xor(BigInteger.MAX_VALUE)", + MIN_VALUE.xor(MAX_VALUE), BigInteger.valueOf(-2)); + try { + BigInteger actual = MIN_VALUE.xor(BigInteger.ONE); + throw new RuntimeException("BigInteger.MIN_VALUE.xor(BigInteger.ONE)).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testNot() { + System.out.println("Testing BigInteger.not"); + check("BigInteger.MIN_VALUE.not()", + MIN_VALUE.not(), MAX_VALUE.subtract(BigInteger.ONE)); + try { + BigInteger actual = MAX_VALUE.not(); + throw new RuntimeException("BigInteger.MAX_VALUE.not()).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testSetBit() { + System.out.println("Testing BigInteger.setBit"); + check("BigInteger.MIN_VALUE.setBit(" + Integer.MAX_VALUE + ")", + MIN_VALUE.setBit(Integer.MAX_VALUE), MIN_VALUE); + try { + BigInteger actual = MAX_VALUE.setBit(Integer.MAX_VALUE); + throw new RuntimeException("BigInteger.MAX_VALUE.setBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testClearBit() { + System.out.println("Testing BigInteger.clearBit"); + check("BigInteger.MAX_VALUE.clearBit(" + Integer.MAX_VALUE + ")", + MAX_VALUE.clearBit(Integer.MAX_VALUE), MAX_VALUE); + try { + BigInteger actual = MIN_VALUE.clearBit(Integer.MAX_VALUE); + throw new RuntimeException("BigInteger.MIN_VALUE.clearBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + try { + BigInteger actual = MIN_VALUE.clearBit(0); + throw new RuntimeException("BigInteger.MIN_VALUE.clearBit(0).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testFlipBit() { + System.out.println("Testing BigInteger.flipBit"); + try { + BigInteger actual = MIN_VALUE.flipBit(Integer.MAX_VALUE); + throw new RuntimeException("BigInteger.MIN_VALUE.flipBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + try { + BigInteger actual = MIN_VALUE.flipBit(0); + throw new RuntimeException("BigInteger.MIN_VALUE.flipBit(0).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + try { + BigInteger actual = MAX_VALUE.flipBit(Integer.MAX_VALUE); + throw new RuntimeException("BigInteger.MAX_VALUE.flipBit(" + Integer.MAX_VALUE + ").bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testGetLowestSetBit() { + System.out.println("Testing BigInteger.getLowestSetBit"); + check("BigInteger.MIN_VALUE.getLowestSetBit()", + MIN_VALUE.getLowestSetBit(), 0); + check("BigInteger.MAX_VALUE.getLowestSetBit()", + MAX_VALUE.getLowestSetBit(), 0); + } + + private static void testBitLength() { + System.out.println("Testing BigInteger.bitLength"); + check("BigInteger.MIN_NEXT.bitLength()", + MIN_VALUE.bitLength(), Integer.MAX_VALUE); + check("BigInteger.MAX_VALUE.bitLength()", + MAX_VALUE.bitLength(), Integer.MAX_VALUE); + } + + private static void testBitCount() { + System.out.println("Testing BigInteger.bitCount"); + check("BigInteger.MIN_VALUE.bitCount()", + MIN_VALUE.bitCount(), Integer.MAX_VALUE - 1); + check("BigInteger.MAX_VALUE.bitCount()", + MAX_VALUE.bitCount(), Integer.MAX_VALUE); + } + + private static void testToString(String msg, int radix, BigInteger bi, int length, String startsWith, char c) { + String s = bi.toString(radix); + if (s.length() != length) { + throw new RuntimeException(msg + ".length=" + s.length()); + } + if (!s.startsWith(startsWith)) { + throw new RuntimeException(msg + "[0]=" + s.substring(0, startsWith.length())); + } + for (int i = startsWith.length(); i < s.length(); i++) { + if (s.charAt(i) != c) { + throw new RuntimeException(msg + "[" + i + "]='" + s.charAt(i) + "'"); + } + } + } + + private static void testToString() { + System.out.println("Testing BigInteger.toString"); + testToString("BigInteger.MIN_VALUE.toString(16)=", 16, + BigInteger.valueOf(-1).shiftLeft(Integer.MAX_VALUE - 1), + (1 << 29) + 1, "-4", '0'); + } + + private static void testToByteArrayWithConstructor(String msg, BigInteger bi, int length, byte msb, byte b, byte lsb) { + byte[] ba = bi.toByteArray(); + if (ba.length != length) { + throw new RuntimeException(msg + ".length=" + ba.length); + } + if (ba[0] != msb) { + throw new RuntimeException(msg + "[0]=" + ba[0]); + } + for (int i = 1; i < ba.length - 1; i++) { + if (ba[i] != b) { + throw new RuntimeException(msg + "[" + i + "]=" + ba[i]); + } + } + if (ba[ba.length - 1] != lsb) { + throw new RuntimeException(msg + "[" + (ba.length - 1) + "]=" + ba[ba.length - 1]); + } + BigInteger actual = new BigInteger(ba); + if (!actual.equals(bi)) { + throw new RuntimeException(msg + ".bitLength()=" + actual.bitLength()); + } + } + + private static void testToByteArrayWithConstructor() { + System.out.println("Testing BigInteger.toByteArray with constructor"); + testToByteArrayWithConstructor("BigInteger.MIN_VALUE.toByteArray()", + MIN_VALUE, (1 << 28), (byte) 0x80, (byte) 0x00, (byte) 0x01); + testToByteArrayWithConstructor("BigInteger.MAX_VALUE.toByteArray()", + MAX_VALUE, (1 << 28), (byte) 0x7f, (byte) 0xff, (byte) 0xff); + + byte[] ba = new byte[1 << 28]; + ba[0] = (byte) 0x80; + try { + BigInteger actual = new BigInteger(-1, ba); + throw new RuntimeException("new BigInteger(-1, ba).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + try { + BigInteger actual = new BigInteger(1, ba); + throw new RuntimeException("new BigInteger(1, ba).bitLength()=" + actual.bitLength()); + } catch (ArithmeticException e) { + // expected + } + } + + private static void testIntValue() { + System.out.println("Testing BigInteger.intValue"); + check("BigInteger.MIN_VALUE.intValue()", + MIN_VALUE.intValue(), 1); + check("BigInteger.MAX_VALUE.floatValue()", + MAX_VALUE.intValue(), -1); + } + + private static void testLongValue() { + System.out.println("Testing BigInteger.longValue"); + check("BigInteger.MIN_VALUE.longValue()", + MIN_VALUE.longValue(), 1L); + check("BigInteger.MAX_VALUE.longValue()", + MAX_VALUE.longValue(), -1L); + } + + private static void testFloatValue() { + System.out.println("Testing BigInteger.floatValue, Bug 8021203"); + check("BigInteger.MIN_VALUE_.floatValue()", + MIN_VALUE.floatValue(), Float.NEGATIVE_INFINITY); + check("BigInteger.MAX_VALUE.floatValue()", + MAX_VALUE.floatValue(), Float.POSITIVE_INFINITY); + } + + private static void testDoubleValue() { + System.out.println("Testing BigInteger.doubleValue, Bug 8021203"); + check("BigInteger.MIN_VALUE.doubleValue()", + MIN_VALUE.doubleValue(), Double.NEGATIVE_INFINITY); + check("BigInteger.MAX_VALUE.doubleValue()", + MAX_VALUE.doubleValue(), Double.POSITIVE_INFINITY); + } + + private static void testSerialization(String msg, BigInteger bi) { + try { + ByteArrayOutputStream baOut = new ByteArrayOutputStream((1 << 28) + 1000); + ObjectOutputStream out = new ObjectOutputStream(baOut); + out.writeObject(bi); + out.close(); + out = null; + byte[] ba = baOut.toByteArray(); + baOut = null; + ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(ba)); + BigInteger actual = (BigInteger) in.readObject(); + if (!actual.equals(bi)) { + throw new RuntimeException(msg + ".bitLength()=" + actual.bitLength()); + } + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(msg + " raised exception ", e); + } + } + + private static void testSerialization() { + System.out.println("Testing BigInteger serialization"); + testSerialization("BigInteger.MIN_VALUE.intValue()", + MIN_VALUE); + testSerialization("BigInteger.MAX_VALUE.floatValue()", + MAX_VALUE); + } + + private static void testLongValueExact() { + System.out.println("Testing BigInteger.longValueExact"); + try { + long actual = MIN_VALUE.longValueExact(); + throw new RuntimeException("BigInteger.MIN_VALUE.longValueExact()= " + actual); + } catch (ArithmeticException e) { + // excpected + } + try { + long actual = MAX_VALUE.longValueExact(); + throw new RuntimeException("BigInteger.MAX_VALUE.longValueExact()= " + actual); + } catch (ArithmeticException e) { + // excpected + } + } + + private static void testIntValueExact() { + System.out.println("Testing BigInteger.intValueExact"); + try { + long actual = MIN_VALUE.intValueExact(); + throw new RuntimeException("BigInteger.MIN_VALUE.intValueExact()= " + actual); + } catch (ArithmeticException e) { + // excpected + } + try { + long actual = MAX_VALUE.intValueExact(); + throw new RuntimeException("BigInteger.MAX_VALUE.intValueExact()= " + actual); + } catch (ArithmeticException e) { + // excpected + } + } + + private static void testShortValueExact() { + System.out.println("Testing BigInteger.shortValueExact"); + try { + long actual = MIN_VALUE.shortValueExact(); + throw new RuntimeException("BigInteger.MIN_VALUE.shortValueExact()= " + actual); + } catch (ArithmeticException e) { + // excpected + } + try { + long actual = MAX_VALUE.shortValueExact(); + throw new RuntimeException("BigInteger.MAX_VALUE.shortValueExact()= " + actual); + } catch (ArithmeticException e) { + // excpected + } + } + + private static void testByteValueExact() { + System.out.println("Testing BigInteger.byteValueExact"); + try { + long actual = MIN_VALUE.byteValueExact(); + throw new RuntimeException("BigInteger.MIN_VALUE.byteValueExact()= " + actual); + } catch (ArithmeticException e) { + // excpected + } + try { + long actual = MAX_VALUE.byteValueExact(); + throw new RuntimeException("BigInteger.MAX_VALUE.byteValueExact()= " + actual); + } catch (ArithmeticException e) { + // excpected + } + } + + public static void main(String... args) { + testOverflowInMakePositive(); + testBug8021204(); + testOverflowInBitSieve(); + testAdd(); + testSubtract(); + testMultiply(); + testDivide(); + testDivideAndRemainder(); + testBug9005933(); + testRemainder(); + testPow(); + testGcd(); + testAbs(); + testNegate(); + testMod(); + testModPow(); +// testModInverse(); + testShiftLeft(); + testShiftRight(); + testAnd(); + testOr(); + testXor(); + testNot(); + testSetBit(); + testClearBit(); + testFlipBit(); + testGetLowestSetBit(); + testBitLength(); + testBitCount(); + testToString(); + testToByteArrayWithConstructor(); + testIntValue(); + testLongValue(); + testFloatValue(); + testDoubleValue(); + testSerialization(); + testLongValueExact(); + testIntValueExact(); + testShortValueExact(); + testByteValueExact(); + } +}