diff --git a/src/main/java/org/apache/commons/validator/routines/BigIntegerValidator.java b/src/main/java/org/apache/commons/validator/routines/BigIntegerValidator.java index 27c44735f..8dc6a6a95 100644 --- a/src/main/java/org/apache/commons/validator/routines/BigIntegerValidator.java +++ b/src/main/java/org/apache/commons/validator/routines/BigIntegerValidator.java @@ -16,6 +16,7 @@ */ package org.apache.commons.validator.routines; +import java.math.BigDecimal; import java.math.BigInteger; import java.text.Format; import java.text.NumberFormat; @@ -157,7 +158,10 @@ public boolean minValue(final BigInteger value, final long min) { */ @Override protected Object processParsedValue(final Object value, final Format formatter) { - return BigInteger.valueOf(((Number) value).longValue()); + if (value instanceof Long) { + return BigInteger.valueOf(((Long) value).longValue()); + } + return new BigDecimal(value.toString()).toBigInteger(); } /** diff --git a/src/test/java/org/apache/commons/validator/routines/BigIntegerValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/BigIntegerValidatorTest.java index 8c2416d12..482b6e85d 100644 --- a/src/test/java/org/apache/commons/validator/routines/BigIntegerValidatorTest.java +++ b/src/test/java/org/apache/commons/validator/routines/BigIntegerValidatorTest.java @@ -134,4 +134,21 @@ void testBigIntegerValidatorMethods() { assertFalse(BigIntegerValidator.getInstance().isValid(xxxx, pattern), "isValid(B) pattern"); assertFalse(BigIntegerValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN), "isValid(B) both"); } + + /** + * Test a value larger than {@link Long#MAX_VALUE} keeps its magnitude instead of being + * clamped to {@link Long#MAX_VALUE}. + */ + @Test + void testBigIntegerAboveLongMaxValue() { + // One past Long.MAX_VALUE, so NumberFormat parses it as a Double rather than a Long. + final BigInteger aboveLong = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); + final String input = aboveLong.toString(); + final BigInteger result = BigIntegerValidator.getInstance().validate(input, "#"); + assertTrue(result.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0, "value clamped to Long.MAX_VALUE"); + assertFalse(BigIntegerValidator.getInstance().maxValue(result, Long.MAX_VALUE), "maxValue should fail for values > Long.MAX_VALUE"); + assertFalse(BigIntegerValidator.getInstance().isInRange(result, Long.MIN_VALUE, Long.MAX_VALUE), "isInRange should fail for values > Long.MAX_VALUE"); + // BigDecimalValidator already preserves the magnitude, so the two must agree + assertEquals(BigDecimalValidator.getInstance().validate(input, "#").toBigInteger(), result); + } }