]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-130959: Reject whitespace in fractions, in pure Python `fromisoformat(...
authorVictor Stinner <vstinner@python.org>
Tue, 11 Mar 2025 11:39:27 +0000 (12:39 +0100)
committerGitHub <noreply@github.com>
Tue, 11 Mar 2025 11:39:27 +0000 (12:39 +0100)
gh-130959: Reject whitespace in fractions, in pure Python `fromisoformat()` (#130962)

Fix the pure Python implementation of `fromisoformat()` to reject any
non-digit characters, including whitespace, in the fractional part
of time specification.  This makes the behavior consistent with the C
implementation, and prevents incorrect parsing of these fractions
(e.g. `.400 ` would be misinterpreted as `.04`).

Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
Co-authored-by: Paul Ganssle <1377457+pganssle@users.noreply.github.com>
(cherry picked from commit 33494b4d0dafc34ff4f1c118b7b3b5d8de3dd0f4)

Co-authored-by: Michał Górny <mgorny@gentoo.org>
Lib/_pydatetime.py
Lib/test/datetimetester.py
Misc/NEWS.d/next/Library/2025-03-07-19-24-27.gh-issue-130959.xO8vVS.rst [new file with mode: 0644]

index e001bd3bbba4b7286de0c52d9822d0cf7f8eefe1..ac1380c12b0a06f08714598458293c71b4b2e066 100644 (file)
@@ -402,6 +402,8 @@ def _parse_hh_mm_ss_ff(tstr):
             raise ValueError("Invalid microsecond component")
         else:
             pos += 1
+            if not all(map(_is_ascii_digit, tstr[pos:])):
+                raise ValueError("Non-digit values in fraction")
 
             len_remainder = len_str - pos
 
@@ -413,9 +415,6 @@ def _parse_hh_mm_ss_ff(tstr):
             time_comps[3] = int(tstr[pos:(pos+to_parse)])
             if to_parse < 6:
                 time_comps[3] *= _FRACTION_CORRECTION[to_parse-1]
-            if (len_remainder > to_parse
-                    and not all(map(_is_ascii_digit, tstr[(pos+to_parse):]))):
-                raise ValueError("Non-digit values in unparsed fraction")
 
     return time_comps
 
index a2ed99a80b76a5e13238f37774c48e1e68c6cf28..952176bee632f7084da6195364beac30b0887414 100644 (file)
@@ -3385,6 +3385,9 @@ class TestDateTime(TestDate):
             '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-19T12:30:45.400 +02:30',  # Space between ms and timezone (gh-130959)
+            '2009-04-19T12:30:45.400 ',        # Trailing space (gh-130959)
+            '2009-04-19T12:30:45. 400',        # Space before fraction (gh-130959)
         ]
 
         for bad_str in bad_strs:
@@ -4469,6 +4472,9 @@ class TestTimeTZ(TestTime, TZInfoBase, unittest.TestCase):
             '12:30:45.123456-',         # Extra at end of microsecond time
             '12:30:45.123456+',         # Extra at end of microsecond time
             '12:30:45.123456+12:00:30a',    # Extra at end of full time
+            '12:30:45.400 +02:30',      # Space between ms and timezone (gh-130959)
+            '12:30:45.400 ',            # Trailing space (gh-130959)
+            '12:30:45. 400',            # Space before fraction (gh-130959)
         ]
 
         for bad_str in bad_strs:
diff --git a/Misc/NEWS.d/next/Library/2025-03-07-19-24-27.gh-issue-130959.xO8vVS.rst b/Misc/NEWS.d/next/Library/2025-03-07-19-24-27.gh-issue-130959.xO8vVS.rst
new file mode 100644 (file)
index 0000000..85f61ca
--- /dev/null
@@ -0,0 +1,3 @@
+Fix pure-Python implementation of :func:`datetime.time.fromisoformat` to reject
+times with spaces in fractional part (for example, ``12:34:56.400 +02:00``),
+matching the C implementation. Patch by Michał Gorny.