diff --git a/src/main/java/org/apache/commons/lang3/time/FastDateParser.java b/src/main/java/org/apache/commons/lang3/time/FastDateParser.java index 21454f375f5..8966fc3f0e4 100644 --- a/src/main/java/org/apache/commons/lang3/time/FastDateParser.java +++ b/src/main/java/org/apache/commons/lang3/time/FastDateParser.java @@ -305,7 +305,15 @@ boolean parse(final FastDateParser parser, final Calendar calendar, final String pos.setErrorIndex(idx); return false; } - final int value = Integer.parseInt(source.substring(pos.getIndex(), idx)); + final int value; + try { + value = Integer.parseInt(source.substring(pos.getIndex(), idx)); + } catch (final NumberFormatException nfe) { + // A run of digits that overflows int cannot be represented by this field; signal a parse failure + // rather than letting NumberFormatException escape the ParsePosition-based parse methods. + pos.setErrorIndex(pos.getIndex()); + return false; + } pos.setIndex(idx); calendar.set(field, modify(parser, value)); return true; diff --git a/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java b/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java index 4e07086a64e..7847cf62b78 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDateParserTest.java @@ -21,6 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; @@ -411,6 +412,20 @@ void testLang1121(final TriFunction dpProv assertEquals(expected, actual); } + @ParameterizedTest + @MethodSource(DATE_PARSER_PARAMETERS) + void testLang1359(final TriFunction dpProvider) { + // A trailing numeric field is unbounded, so a digit run that overflows int must fail the parse + // through the ParsePosition/ParseException contract, not escape as a NumberFormatException. + final DateParser fdp = getInstance(dpProvider, "yyyy", TimeZones.GMT, Locale.US); + final String overflow = "99999999999"; + assertThrows(ParseException.class, () -> fdp.parse(overflow)); + final ParsePosition pos = new ParsePosition(0); + assertNull(fdp.parseObject(overflow, pos)); + assertTrue(pos.getErrorIndex() >= 0); + assertEquals(0, pos.getIndex()); + } + @ParameterizedTest @MethodSource(DATE_PARSER_PARAMETERS) void testLang1380(final TriFunction dpProvider) throws ParseException {