]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-146076: Fix crash when a `ZoneInfo` subclass is missing a `_weak_cache` (#146082)
authorStan Ulbrych <89152624+StanFromIreland@users.noreply.github.com>
Wed, 18 Mar 2026 12:58:08 +0000 (12:58 +0000)
committerGitHub <noreply@github.com>
Wed, 18 Mar 2026 12:58:08 +0000 (18:28 +0530)
Lib/test/test_zoneinfo/test_zoneinfo.py
Misc/NEWS.d/next/Library/2026-03-17-20-41-27.gh-issue-146076.yoBNnB.rst [new file with mode: 0644]
Modules/_zoneinfo.c

index a5dea802a9898dd1437399c65d4a357d6fa0b454..aaab4709464fd01cc25258087d45b6929b8f6dbc 100644 (file)
@@ -1595,6 +1595,18 @@ class CZoneInfoCacheTest(ZoneInfoCacheTest):
             "Unexpected instance of int in ZI weak cache for key 'America/Los_Angeles'"
         )
 
+    def test_deleted_weak_cache(self):
+        class ZI(self.klass):
+            pass
+        delattr(ZI, '_weak_cache')
+
+        # These should not segfault
+        with self.assertRaises(AttributeError):
+            ZI("UTC")
+
+        with self.assertRaises(AttributeError):
+            ZI.clear_cache()
+
     def test_inconsistent_weak_cache_setdefault(self):
         class Cache:
             def get(self, key, default=None):
diff --git a/Misc/NEWS.d/next/Library/2026-03-17-20-41-27.gh-issue-146076.yoBNnB.rst b/Misc/NEWS.d/next/Library/2026-03-17-20-41-27.gh-issue-146076.yoBNnB.rst
new file mode 100644 (file)
index 0000000..746f5b2
--- /dev/null
@@ -0,0 +1,2 @@
+:mod:`zoneinfo`: fix crashes when deleting ``_weak_cache`` from a
+:class:`zoneinfo.ZoneInfo` subclass.
index 39671d1ab51dfa58711554f3dba387e478657c22..e2ab04cc2073c58905583b2eb636e921a90e1021 100644 (file)
@@ -321,6 +321,9 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key)
     }
 
     PyObject *weak_cache = get_weak_cache(state, type);
+    if (weak_cache == NULL) {
+        return NULL;
+    }
     instance = PyObject_CallMethod(weak_cache, "get", "O", key, Py_None);
     if (instance == NULL) {
         Py_DECREF(weak_cache);
@@ -505,6 +508,9 @@ zoneinfo_ZoneInfo_clear_cache_impl(PyTypeObject *type, PyTypeObject *cls,
 {
     zoneinfo_state *state = zoneinfo_get_state_by_cls(cls);
     PyObject *weak_cache = get_weak_cache(state, type);
+    if (weak_cache == NULL) {
+        return NULL;
+    }
 
     if (only_keys == NULL || only_keys == Py_None) {
         PyObject *rv = PyObject_CallMethod(weak_cache, "clear", NULL);