Skip to content

Commit 322ec8e

Browse files
authored
Merge pull request #397 from garydgregory/fix/BigIntegerValidator_out_of_long_range
Fix BigIntegerValidator minValue(), maxValue(), and processParsedValue() for out of Long range values.
2 parents 8f6d35c + eafeda9 commit 322ec8e

2 files changed

Lines changed: 55 additions & 3 deletions

File tree

src/main/java/org/apache/commons/validator/routines/BigIntegerValidator.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717
package org.apache.commons.validator.routines;
1818

19+
import java.math.BigDecimal;
1920
import java.math.BigInteger;
2021
import java.text.Format;
2122
import java.text.NumberFormat;
@@ -120,7 +121,7 @@ public BigIntegerValidator(final boolean strict, final int formatType) {
120121
* specified range.
121122
*/
122123
public boolean isInRange(final BigInteger value, final long min, final long max) {
123-
return value.longValue() >= min && value.longValue() <= max;
124+
return value.compareTo(BigInteger.valueOf(min)) >= 0 && value.compareTo(BigInteger.valueOf(max)) <= 0;
124125
}
125126

126127
/**
@@ -132,7 +133,7 @@ public boolean isInRange(final BigInteger value, final long min, final long max)
132133
* or equal to the maximum.
133134
*/
134135
public boolean maxValue(final BigInteger value, final long max) {
135-
return value.longValue() <= max;
136+
return value.compareTo(BigInteger.valueOf(max)) <= 0;
136137
}
137138

138139
/**
@@ -157,7 +158,14 @@ public boolean minValue(final BigInteger value, final long min) {
157158
*/
158159
@Override
159160
protected Object processParsedValue(final Object value, final Format formatter) {
160-
return BigInteger.valueOf(((Number) value).longValue());
161+
if (value instanceof Long) {
162+
return BigInteger.valueOf(((Long) value).longValue());
163+
}
164+
if (value instanceof Double) {
165+
// No need to roundtrip with a string.
166+
return BigDecimal.valueOf(((Double) value).doubleValue()).toBigInteger();
167+
}
168+
return new BigDecimal(value.toString()).toBigInteger();
161169
}
162170

163171
/**

src/test/java/org/apache/commons/validator/routines/BigIntegerValidatorTest.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,50 @@ protected void setUp() {
7070

7171
}
7272

73+
/**
74+
* Test a value larger than {@link Long#MAX_VALUE} keeps its magnitude instead of being clamped to {@link Long#MAX_VALUE}.
75+
*/
76+
@Test
77+
void testBigIntegerAboveLongMaxValue() {
78+
// One past Long.MAX_VALUE, so NumberFormat parses it as a Double rather than a Long.
79+
final BigInteger aboveLong = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE);
80+
final String aboveLongStr = aboveLong.toString();
81+
final BigIntegerValidator instance = BigIntegerValidator.getInstance();
82+
final BigInteger resultAboveLong = instance.validate(aboveLongStr, "#");
83+
assertTrue(resultAboveLong.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) > 0);
84+
assertTrue(resultAboveLong.compareTo(BigInteger.ZERO) > 0);
85+
assertTrue(resultAboveLong.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0);
86+
assertTrue(instance.minValue(resultAboveLong, Long.MIN_VALUE));
87+
assertFalse(instance.minValue(resultAboveLong, Long.MAX_VALUE));
88+
assertFalse(instance.maxValue(resultAboveLong, Long.MIN_VALUE));
89+
assertFalse(instance.maxValue(resultAboveLong, Long.MAX_VALUE));
90+
assertFalse(instance.isInRange(resultAboveLong, Long.MIN_VALUE, Long.MAX_VALUE));
91+
// BigDecimalValidator already preserves the magnitude, so the two must agree
92+
assertEquals(BigDecimalValidator.getInstance().validate(aboveLongStr, "#").toBigInteger(), resultAboveLong);
93+
}
94+
95+
/**
96+
* Test a value larger than {@link Long#MAX_VALUE} keeps its magnitude instead of being clamped to {@link Long#MAX_VALUE}.
97+
*/
98+
@Test
99+
void testBigIntegerBelowLongMinValue() {
100+
// One past Long.MAX_VALUE, so NumberFormat parses it as a Double rather than a Long.
101+
final BigInteger belowLong = BigInteger.valueOf(Long.MIN_VALUE).subtract(BigInteger.ONE);
102+
final String belowLongStr = belowLong.toString();
103+
final BigIntegerValidator instance = BigIntegerValidator.getInstance();
104+
final BigInteger resultBelowLong = instance.validate(belowLongStr, "#");
105+
assertTrue(resultBelowLong.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0);
106+
assertTrue(resultBelowLong.compareTo(BigInteger.ZERO) < 0);
107+
assertTrue(resultBelowLong.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) < 0);
108+
assertTrue(instance.minValue(resultBelowLong, Long.MIN_VALUE));
109+
assertFalse(instance.minValue(resultBelowLong, Long.MAX_VALUE));
110+
assertTrue(instance.maxValue(resultBelowLong, Long.MIN_VALUE));
111+
assertTrue(instance.maxValue(resultBelowLong, Long.MAX_VALUE));
112+
assertFalse(instance.isInRange(resultBelowLong, Long.MIN_VALUE, Long.MAX_VALUE));
113+
// BigDecimalValidator already preserves the magnitude, so the two must agree
114+
assertEquals(BigDecimalValidator.getInstance().validate(belowLongStr, "#").toBigInteger(), resultBelowLong);
115+
}
116+
73117
/**
74118
* Test BigInteger Range/Min/Max
75119
*/

0 commit comments

Comments
 (0)