NumberUtils consistently raises overflow exception for BigInteger/BigDecimal input
Issue: SPR-14041
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -87,39 +87,29 @@ public abstract class NumberUtils {
|
||||
return (T) number;
|
||||
}
|
||||
else if (Byte.class == targetClass) {
|
||||
long value = number.longValue();
|
||||
long value = checkedLongValue(number, targetClass);
|
||||
if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
|
||||
raiseOverflowException(number, targetClass);
|
||||
}
|
||||
return (T) Byte.valueOf(number.byteValue());
|
||||
}
|
||||
else if (Short.class == targetClass) {
|
||||
long value = number.longValue();
|
||||
long value = checkedLongValue(number, targetClass);
|
||||
if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
|
||||
raiseOverflowException(number, targetClass);
|
||||
}
|
||||
return (T) Short.valueOf(number.shortValue());
|
||||
}
|
||||
else if (Integer.class == targetClass) {
|
||||
long value = number.longValue();
|
||||
long value = checkedLongValue(number, targetClass);
|
||||
if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) {
|
||||
raiseOverflowException(number, targetClass);
|
||||
}
|
||||
return (T) Integer.valueOf(number.intValue());
|
||||
}
|
||||
else if (Long.class == targetClass) {
|
||||
BigInteger bigInt = null;
|
||||
if (number instanceof BigInteger) {
|
||||
bigInt = (BigInteger) number;
|
||||
}
|
||||
else if (number instanceof BigDecimal) {
|
||||
bigInt = ((BigDecimal) number).toBigInteger();
|
||||
}
|
||||
// Effectively analogous to JDK 8's BigInteger.longValueExact()
|
||||
if (bigInt != null && (bigInt.compareTo(LONG_MIN) < 0 || bigInt.compareTo(LONG_MAX) > 0)) {
|
||||
raiseOverflowException(number, targetClass);
|
||||
}
|
||||
return (T) Long.valueOf(number.longValue());
|
||||
long value = checkedLongValue(number, targetClass);
|
||||
return (T) Long.valueOf(value);
|
||||
}
|
||||
else if (BigInteger.class == targetClass) {
|
||||
if (number instanceof BigDecimal) {
|
||||
@@ -148,11 +138,35 @@ public abstract class NumberUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for a {@code BigInteger}/{@code BigDecimal} long overflow
|
||||
* before returning the given number as a long value.
|
||||
* @param number the number to convert
|
||||
* @param targetClass the target class to convert to
|
||||
* @return the long value, if convertible without overflow
|
||||
* @throws IllegalArgumentException if there is an overflow
|
||||
* @see #raiseOverflowException
|
||||
*/
|
||||
private static long checkedLongValue(Number number, Class<? extends Number> targetClass) {
|
||||
BigInteger bigInt = null;
|
||||
if (number instanceof BigInteger) {
|
||||
bigInt = (BigInteger) number;
|
||||
}
|
||||
else if (number instanceof BigDecimal) {
|
||||
bigInt = ((BigDecimal) number).toBigInteger();
|
||||
}
|
||||
// Effectively analogous to JDK 8's BigInteger.longValueExact()
|
||||
if (bigInt != null && (bigInt.compareTo(LONG_MIN) < 0 || bigInt.compareTo(LONG_MAX) > 0)) {
|
||||
raiseOverflowException(number, targetClass);
|
||||
}
|
||||
return number.longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Raise an <em>overflow</em> exception for the given number and target class.
|
||||
* @param number the number we tried to convert
|
||||
* @param targetClass the target class we tried to convert to
|
||||
* @throws IllegalArgumentException
|
||||
* @throws IllegalArgumentException if there is an overflow
|
||||
*/
|
||||
private static void raiseOverflowException(Number number, Class<?> targetClass) {
|
||||
throw new IllegalArgumentException("Could not convert number [" + number + "] of type [" +
|
||||
|
||||
Reference in New Issue
Block a user