]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-154892: Fix `PyLong_AsLong()` error checks in `_zoneinfo` (#154901) main
authorBhuvansh <bhuvanshkataria@gmail.com>
Sat, 1 Aug 2026 19:54:04 +0000 (19:54 +0000)
committerGitHub <noreply@github.com>
Sat, 1 Aug 2026 19:54:04 +0000 (21:54 +0200)
Co-authored-by: Stan Ulbrych <stan@python.org>
Lib/test/test_zoneinfo/test_zoneinfo.py
Misc/NEWS.d/next/Library/2026-07-29-21-37-39.gh-issue-154892.eQyJ3Z.rst [new file with mode: 0644]
Modules/_zoneinfo.c

index a10f434eb27590d13011364dce3bcec64b3a5405..41ba92342ff2cbd6a5a23faad2183a01c9cab064 100644 (file)
@@ -316,6 +316,18 @@ class ZoneInfoTest(TzPathUserMixin, ZoneInfoTestBase):
                 self.assertEqual(dt.utcoffset(), offset.utcoffset, dt)
                 self.assertEqual(dt.dst(), offset.dst, dt)
 
+    def test_datetime_subclass_negative_components(self):
+        class MinusOneDateTime(datetime):
+            hour = minute = second = -1
+
+        zi = self.zone_from_key("UTC")
+        dt = MinusOneDateTime(2024, 1, 1, tzinfo=zi)
+
+        self.assertEqual(dt.utcoffset(), ZERO)
+        self.assertEqual(dt.dst(), ZERO)
+        self.assertEqual(dt.tzname(), "UTC")
+        self.assertEqual(zi.fromutc(dt), datetime(2024, 1, 1, tzinfo=zi))
+
     def test_folds_and_gaps(self):
         test_cases = []
         for key in self.zones():
diff --git a/Misc/NEWS.d/next/Library/2026-07-29-21-37-39.gh-issue-154892.eQyJ3Z.rst b/Misc/NEWS.d/next/Library/2026-07-29-21-37-39.gh-issue-154892.eQyJ3Z.rst
new file mode 100644 (file)
index 0000000..5088b04
--- /dev/null
@@ -0,0 +1,3 @@
+Fix a bug in the C accelerator for :mod:`zoneinfo` where
+:class:`datetime.datetime` subclasses returning ``-1`` for ``hour``,
+``minute``, or ``second`` could incorrectly raise a :exc:`SystemError`.
index 2a7ac4498261e08c4e28c41f1fe285b2391d5241..464e145438ae733b93607ccbb8f7ceb6041b9016 100644 (file)
@@ -2311,7 +2311,7 @@ get_local_timestamp(PyObject *dt, int64_t *local_ts)
         }
         hour = PyLong_AsLong(num);
         Py_DECREF(num);
-        if (hour == -1) {
+        if (hour == -1 && PyErr_Occurred()) {
             return -1;
         }
 
@@ -2321,7 +2321,7 @@ get_local_timestamp(PyObject *dt, int64_t *local_ts)
         }
         minute = PyLong_AsLong(num);
         Py_DECREF(num);
-        if (minute == -1) {
+        if (minute == -1 && PyErr_Occurred()) {
             return -1;
         }
 
@@ -2331,7 +2331,7 @@ get_local_timestamp(PyObject *dt, int64_t *local_ts)
         }
         second = PyLong_AsLong(num);
         Py_DECREF(num);
-        if (second == -1) {
+        if (second == -1 && PyErr_Occurred()) {
             return -1;
         }
     }