Skip to content

Commit b5380cf

Browse files
author
Morten Haraldsen
committed
Add overflow check. Limit each individual section to 32-bit signed
1 parent 5b3505c commit b5380cf

File tree

2 files changed

+25
-3
lines changed

2 files changed

+25
-3
lines changed

src/main/java/com/ethlo/time/ItuDurationParser.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,15 @@ private static int readUntilNonDigit(final String chars, final int offset, final
9494
}
9595
else
9696
{
97-
value = value * RADIX + (c - ZERO);
97+
int digit = c - ZERO;
98+
99+
// Correct overflow check
100+
if (value > 214748364 || (value == 214748364 && digit > 7))
101+
{
102+
throw new DateTimeParseException("Numeric overflow while parsing value", chars, idx);
103+
}
104+
105+
value = value * RADIX + digit;
98106
idx++;
99107
}
100108
}
@@ -198,6 +206,12 @@ public final void accept(final String chars, final int index, final int length,
198206
throw new DateTimeParseException("Duration must start with 'P'", chars, 0);
199207
}
200208

209+
/*
210+
* An int can never overflow a long when used for seconds, minutes, hours, days, and weeks,
211+
* even at their maximum values, because the total number of seconds remains within the
212+
* 64-bit long's limits.
213+
*/
214+
201215
switch (unit)
202216
{
203217
case 'T':
@@ -248,7 +262,7 @@ public final void accept(final String chars, final int index, final int length,
248262
int remainingDigits = DIGITS_IN_NANO - length;
249263
if (remainingDigits > 0)
250264
{
251-
nano *= POW10_TABLE[remainingDigits]; // Use lookup instead of loop
265+
nano *= POW10_TABLE[remainingDigits];
252266
}
253267
readingFractionalPart = false;
254268
}

src/test/java/com/ethlo/time/ItuDurationParserTest.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ void testValidFullNotNormalizedToNormalized()
5656
@Test
5757
void shouldParseZeroDuration()
5858
{
59-
// Input: P0D (zero duration)
6059
Duration duration = ItuDurationParser.parse("P0D").toDuration();
6160
assertThat(duration).isEqualTo(Duration.ZERO);
6261
}
@@ -77,6 +76,15 @@ void shouldParseDurationWithNoTimeSection()
7776
assertThat(duration).isEqualTo(Duration.ofDays(30));
7877
}
7978

79+
@Test
80+
void shouldThrowDateTimeParseExceptionForOverflow()
81+
{
82+
final String input = "P999999999999D";
83+
assertThatThrownBy(() -> ItuDurationParser.parse(input))
84+
.isInstanceOf(DateTimeParseException.class)
85+
.hasMessageContaining("Numeric overflow while parsing value");
86+
}
87+
8088
@Test
8189
void shouldThrowDateTimeParseExceptionForInvalidUnits()
8290
{

0 commit comments

Comments
 (0)