]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-117534: Add checking for input parameter in iso_to_ymd (#117543)
authorVlad4896 <166005126+Vlad4896@users.noreply.github.com>
Tue, 9 Apr 2024 17:53:00 +0000 (20:53 +0300)
committerGitHub <noreply@github.com>
Tue, 9 Apr 2024 17:53:00 +0000 (13:53 -0400)
Moves the validation for invalid years in the C implementation of the `datetime` module into a common location between `fromisoformat` and `fromisocalendar`, which improves the error message and fixes a failed assertion when parsing invalid ISO 8601 years using one of the "ISO weeks" formats.

---------

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Lib/test/datetimetester.py
Misc/ACKS
Misc/NEWS.d/next/C API/2024-04-08-09-44-29.gh-issue-117534.54ZE_n.rst [new file with mode: 0644]
Modules/_datetimemodule.c

index c77263998c99f51abe5ac3bfe623081a45e54da9..570110893629cf19b4fb41cef51154773a19343a 100644 (file)
@@ -1927,6 +1927,10 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase):
             '2009-02-29',       # Invalid leap day
             '2019-W53-1',       # No week 53 in 2019
             '2020-W54-1',       # No week 54
+            '0000-W25-1',       # Invalid year
+            '10000-W25-1',      # Invalid year
+            '2020-W25-0',       # Invalid day-of-week
+            '2020-W25-8',       # Invalid day-of-week
             '2009\ud80002\ud80028',     # Separators are surrogate codepoints
         ]
 
index fe014a364dd82da85ebacd4214b3ac336f3886ee..a108ec37d4425eb496e4ae65de624f9ee0084e18 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -496,6 +496,7 @@ David Edelsohn
 John Edmonds
 Benjamin Edwards
 Grant Edwards
+Vlad Efanov
 Zvi Effron
 John Ehresman
 Tal Einat
diff --git a/Misc/NEWS.d/next/C API/2024-04-08-09-44-29.gh-issue-117534.54ZE_n.rst b/Misc/NEWS.d/next/C API/2024-04-08-09-44-29.gh-issue-117534.54ZE_n.rst
new file mode 100644 (file)
index 0000000..4b7dda6
--- /dev/null
@@ -0,0 +1,2 @@
+Improve validation logic in the C implementation of :meth:`datetime.fromisoformat`
+to better handle invalid years. Patch by Vlad Efanov.
index a626bda2ea9be9f66434f7f54937134c2a5873e9..2c9ef4b52851b75b6e85c66d35849f34af48764f 100644 (file)
@@ -416,6 +416,10 @@ iso_week1_monday(int year)
 static int
 iso_to_ymd(const int iso_year, const int iso_week, const int iso_day,
            int *year, int *month, int *day) {
+    // Year is bounded to 0 < year < 10000 because 9999-12-31 is (9999, 52, 5)
+    if (iso_year < MINYEAR || iso_year > MAXYEAR) {
+        return -4;
+    }
     if (iso_week <= 0 || iso_week >= 53) {
         int out_of_range = 1;
         if (iso_week == 53) {
@@ -762,7 +766,7 @@ parse_isoformat_date(const char *dtstr, const size_t len, int *year, int *month,
      *      -2:  Inconsistent date separator usage
      *      -3:  Failed to parse ISO week.
      *      -4:  Failed to parse ISO day.
-     *      -5, -6: Failure in iso_to_ymd
+     *      -5, -6, -7: Failure in iso_to_ymd
      */
     const char *p = dtstr;
     p = parse_digits(p, year, 4);
@@ -3142,15 +3146,13 @@ date_fromisocalendar(PyObject *cls, PyObject *args, PyObject *kw)
         return NULL;
     }
 
-    // Year is bounded to 0 < year < 10000 because 9999-12-31 is (9999, 52, 5)
-    if (year < MINYEAR || year > MAXYEAR) {
-        PyErr_Format(PyExc_ValueError, "Year is out of range: %d", year);
-        return NULL;
-    }
-
     int month;
     int rv = iso_to_ymd(year, week, day, &year, &month, &day);
 
+    if (rv == -4) {
+        PyErr_Format(PyExc_ValueError, "Year is out of range: %d", year);
+        return NULL;
+    }
 
     if (rv == -2) {
         PyErr_Format(PyExc_ValueError, "Invalid week: %d", week);