From ae18b325ffe5d77dc8ebde75ee765ae3dc1d50ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Eiras?= Date: Tue, 8 Aug 2023 22:31:36 +0200 Subject: [PATCH] gh-107779: in datetime.fromisoformat, check the separator between date and time --- Lib/_pydatetime.py | 7 ++++++- Lib/test/datetimetester.py | 3 +++ Modules/_datetimemodule.c | 6 ++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Lib/_pydatetime.py b/Lib/_pydatetime.py index f4fc2c58e5e2937..2aea449479797d8 100644 --- a/Lib/_pydatetime.py +++ b/Lib/_pydatetime.py @@ -1862,13 +1862,18 @@ def fromisoformat(cls, date_string): try: separator_location = _find_isoformat_datetime_separator(date_string) dstr = date_string[0:separator_location] - tstr = date_string[(separator_location+1):] + sep = date_string[separator_location:separator_location+1] + tstr = date_string[separator_location+1:] date_components = _parse_isoformat_date(dstr) except ValueError: raise ValueError( f'Invalid isoformat string: {date_string!r}') from None + if sep and (_is_ascii_digit(sep) or not tstr): + # Date and time most likely split at the wrong place, indicates wrong format. + raise ValueError(f'Invalid isoformat string: {date_string!r}') + if tstr: try: time_components = _parse_isoformat_time(tstr) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 55e061950ff2806..833d5c7d63487f1 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -1909,6 +1909,7 @@ def test_fromisoformat_fails(self): '2019-W53-1', # No week 53 in 2019 '2020-W54-1', # No week 54 '2009\ud80002\ud80028', # Separators are surrogate codepoints + '2009-01-01 ', # Trailing separator without time component ] for bad_str in bad_strs: @@ -3295,6 +3296,8 @@ def test_fromisoformat_fails_datetime(self): '2009-04-19T12:30:45.123456-05:00a', # Extra text '2009-04-19T12:30:45.123-05:00a', # Extra text '2009-04-19T12:30:45-05:00a', # Extra text + '2009-04-1912:30:45', # Missing date-time separator 1 + '20090419123054', # Missing date-time separator 2 ] for bad_str in bad_strs: diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 9002a1de7fb5b76..eb41200705fb733 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -5451,6 +5451,12 @@ datetime_fromisoformat(PyObject *cls, PyObject *dtstr) if (!rv && len > separator_location) { // In UTF-8, the length of multi-byte characters is encoded in the MSB p += separator_location; + + if (is_digit(p[0])) { + // Date and time most likely split at the wrong place, indicates wrong format. + goto invalid_string_error; + } + if ((p[0] & 0x80) == 0) { p += 1; }