Skip to content

Commit 112c69a

Browse files
pythongh-152157: Reject empty fractions in _datetime.{date}time.fromisoformat (python#152161)
Co-authored-by: Stan Ulbrych <stan@python.org>
1 parent 711e811 commit 112c69a

3 files changed

Lines changed: 24 additions & 8 deletions

File tree

Lib/test/datetimetester.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3758,6 +3758,10 @@ def test_fromisoformat_fails_datetime(self):
37583758
'2009-04-19T12:30:45-00:90:00', # Time zone field out from range
37593759
'2009-04-19T12:30:45-00:00:90', # Time zone field out from range
37603760
'2020-2020', # Ambiguous 9-char date portion
3761+
'2009-04-19T12:30:45.+05:00', # Empty fraction before offset
3762+
'2009-04-19T12:30:45.-05:00', # Empty fraction before offset
3763+
'2009-04-19T12:30:45.Z', # Empty fraction before Z
3764+
'2009-04-19T12:30:45,+05:00', # Empty fraction (comma) before offset
37613765
]
37623766

37633767
for bad_str in bad_strs:
@@ -5034,6 +5038,10 @@ def test_fromisoformat_fails(self):
50345038
'24:01:00.000000', # Has non-zero minutes on 24:00
50355039
'12:30:45+00:90:00', # Time zone field out from range
50365040
'12:30:45+00:00:90', # Time zone field out from range
5041+
'12:30:45.+05:00', # Empty fraction before offset
5042+
'12:30:45.-05:00', # Empty fraction before offset
5043+
'12:30:45.Z', # Empty fraction before Z
5044+
'12:30:45,+05:00', # Empty fraction (comma) before offset
50375045
]
50385046

50395047
for bad_str in bad_strs:
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
The C implementations of :meth:`~datetime.datetime.fromisoformat` and :meth:`~datetime.time.fromisoformat`
2+
now reject a decimal separator that is not followed by any
3+
fractional digit before a timezone designator.

Modules/_datetimemodule.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,7 +1034,16 @@ parse_hh_mm_ss_ff(const char *tstr, const char *tstr_end, int *hour,
10341034
has_separator = (c == ':');
10351035
}
10361036

1037-
if (p >= p_end) {
1037+
if (c == '.' || c == ',') {
1038+
if (i < 2) {
1039+
return -3; // Decimal mark on hour or minute
1040+
}
1041+
if (p >= p_end) {
1042+
return -3; // Decimal mark not followed by any digit
1043+
}
1044+
break;
1045+
}
1046+
else if (p >= p_end) {
10381047
return c != '\0';
10391048
}
10401049
else if (has_separator && (c == ':')) {
@@ -1043,14 +1052,10 @@ parse_hh_mm_ss_ff(const char *tstr, const char *tstr_end, int *hour,
10431052
}
10441053
continue;
10451054
}
1046-
else if (c == '.' || c == ',') {
1047-
if (i < 2) {
1048-
return -3; // Decimal mark on hour or minute
1049-
}
1050-
break;
1051-
} else if (!has_separator) {
1055+
else if (!has_separator) {
10521056
--p;
1053-
} else {
1057+
}
1058+
else {
10541059
return -4; // Malformed time separator
10551060
}
10561061
}

0 commit comments

Comments
 (0)