diff --git a/lib/src/types/xsd_date.dart b/lib/src/types/xsd_date.dart index 0f8b860..983521a 100644 --- a/lib/src/types/xsd_date.dart +++ b/lib/src/types/xsd_date.dart @@ -67,17 +67,19 @@ class XsdDate implements Comparable { if (tzStr == null) { return XsdDate(dt, isFloating: true); } else { - Duration? offset; + final Duration offset; if (tzStr == 'Z') { offset = Duration.zero; } else { - final tzMatch = _offsetRegex.firstMatch(tzStr); - if (tzMatch != null) { - final sign = tzMatch.group(1) == '+' ? 1 : -1; - final hours = int.parse(tzMatch.group(2)!); - final minutes = int.parse(tzMatch.group(3)!); - offset = Duration(hours: hours, minutes: minutes) * sign; + // _dateRegex ensures tzStr is in [+-]HH:mm format, so a match is guaranteed. + final tzMatch = _offsetRegex.firstMatch(tzStr)!; + final sign = tzMatch.group(1) == '+' ? 1 : -1; + final hours = int.parse(tzMatch.group(2)!); + final minutes = int.parse(tzMatch.group(3)!); + if (hours > 14 || minutes > 59 || (hours == 14 && minutes != 0)) { + throw FormatException('Invalid timezone offset range', input); } + offset = Duration(hours: hours, minutes: minutes) * sign; } return XsdDate(dt, isFloating: false, originalOffset: offset); } diff --git a/test/types/xsd_date_test.dart b/test/types/xsd_date_test.dart index 48eedb0..9b9ac08 100644 --- a/test/types/xsd_date_test.dart +++ b/test/types/xsd_date_test.dart @@ -58,6 +58,18 @@ void main() { () => XsdDate.parse('2002-02-30'), throwsFormatException, ); // Invalid day + expect( + () => XsdDate.parse('2002-10-10+15:00'), // Hour > 14 + throwsFormatException, + ); + expect( + () => XsdDate.parse('2002-10-10-14:01'), // Minute > 00 when hour is 14 + throwsFormatException, + ); + expect( + () => XsdDate.parse('2002-10-10+05:60'), // Minute > 59 + throwsFormatException, + ); }); test('equality', () {