https://github.com/python/cpython/commit/63da6c86eb7e10b04ce39d3dff70e77a1ace4255
commit: 63da6c86eb7e10b04ce39d3dff70e77a1ace4255
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: StanFromIreland <[email protected]>
date: 2026-07-01T10:23:08Z
summary:
[3.15] gh-152157: Reject empty fractions in
`_datetime.{date}time.fromisoformat` (GH-152161) (#152761)
(cherry picked from commit 112c69a0514902af2d2f7d0503de6690ca59a10f)
Co-authored-by: tonghuaroot (童话) <[email protected]>
Co-authored-by: Stan Ulbrych <[email protected]>
files:
A Misc/NEWS.d/next/Library/2026-06-25-07-08-17.gh-issue-152157.dt5Ef0.rst
M Lib/test/datetimetester.py
M Modules/_datetimemodule.c
diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py
index 192b22ff7540034..c11e9c068bed3bd 100644
--- a/Lib/test/datetimetester.py
+++ b/Lib/test/datetimetester.py
@@ -3758,6 +3758,10 @@ def test_fromisoformat_fails_datetime(self):
'2009-04-19T12:30:45-00:90:00', # Time zone field out from range
'2009-04-19T12:30:45-00:00:90', # Time zone field out from range
'2020-2020', # Ambiguous 9-char date portion
+ '2009-04-19T12:30:45.+05:00', # Empty fraction before offset
+ '2009-04-19T12:30:45.-05:00', # Empty fraction before offset
+ '2009-04-19T12:30:45.Z', # Empty fraction before Z
+ '2009-04-19T12:30:45,+05:00', # Empty fraction (comma) before
offset
]
for bad_str in bad_strs:
@@ -5034,6 +5038,10 @@ def test_fromisoformat_fails(self):
'24:01:00.000000', # Has non-zero minutes on 24:00
'12:30:45+00:90:00', # Time zone field out from range
'12:30:45+00:00:90', # Time zone field out from range
+ '12:30:45.+05:00', # Empty fraction before offset
+ '12:30:45.-05:00', # Empty fraction before offset
+ '12:30:45.Z', # Empty fraction before Z
+ '12:30:45,+05:00', # Empty fraction (comma) before offset
]
for bad_str in bad_strs:
diff --git
a/Misc/NEWS.d/next/Library/2026-06-25-07-08-17.gh-issue-152157.dt5Ef0.rst
b/Misc/NEWS.d/next/Library/2026-06-25-07-08-17.gh-issue-152157.dt5Ef0.rst
new file mode 100644
index 000000000000000..00e83b4af6be7a9
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-06-25-07-08-17.gh-issue-152157.dt5Ef0.rst
@@ -0,0 +1,3 @@
+The C implementations of :meth:`~datetime.datetime.fromisoformat` and
:meth:`~datetime.time.fromisoformat`
+now reject a decimal separator that is not followed by any
+fractional digit before a timezone designator.
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index d52969bef0070f7..d218c989891c1b1 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -1034,7 +1034,16 @@ parse_hh_mm_ss_ff(const char *tstr, const char
*tstr_end, int *hour,
has_separator = (c == ':');
}
- if (p >= p_end) {
+ if (c == '.' || c == ',') {
+ if (i < 2) {
+ return -3; // Decimal mark on hour or minute
+ }
+ if (p >= p_end) {
+ return -3; // Decimal mark not followed by any digit
+ }
+ break;
+ }
+ else if (p >= p_end) {
return c != '\0';
}
else if (has_separator && (c == ':')) {
@@ -1043,14 +1052,10 @@ parse_hh_mm_ss_ff(const char *tstr, const char
*tstr_end, int *hour,
}
continue;
}
- else if (c == '.' || c == ',') {
- if (i < 2) {
- return -3; // Decimal mark on hour or minute
- }
- break;
- } else if (!has_separator) {
+ else if (!has_separator) {
--p;
- } else {
+ }
+ else {
return -4; // Malformed time separator
}
}
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]