gh-142781: Fix type confusion in zoneinfo weak cache (GH-142925)

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Co-authored-by: Stan Ulbrych <89152624+StanFromIreland@users.noreply.github.com>
This commit is contained in:
zhong 2026-03-02 20:30:38 +08:00 committed by GitHub
parent e542255458
commit b611db491d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 50 additions and 1 deletions

View file

@ -1577,6 +1577,44 @@ class EvilZoneInfo(self.klass):
class CZoneInfoCacheTest(ZoneInfoCacheTest):
module = c_zoneinfo
def test_inconsistent_weak_cache_get(self):
class Cache:
def get(self, key, default=None):
return 1337
class ZI(self.klass):
pass
# Class attribute must be set after class creation
# to override zoneinfo.ZoneInfo.__init_subclass__.
ZI._weak_cache = Cache()
with self.assertRaises(RuntimeError) as te:
ZI("America/Los_Angeles")
self.assertEqual(
str(te.exception),
"Unexpected instance of int in ZI weak cache for key 'America/Los_Angeles'"
)
def test_inconsistent_weak_cache_setdefault(self):
class Cache:
def get(self, key, default=None):
return default
def setdefault(self, key, value):
return 1337
class ZI(self.klass):
pass
# Class attribute must be set after class creation
# to override zoneinfo.ZoneInfo.__init_subclass__.
ZI._weak_cache = Cache()
with self.assertRaises(RuntimeError) as te:
ZI("America/Los_Angeles")
self.assertEqual(
str(te.exception),
"Unexpected instance of int in ZI weak cache for key 'America/Los_Angeles'"
)
class ZoneInfoPickleTest(TzPathUserMixin, ZoneInfoTestBase):
module = py_zoneinfo

View file

@ -0,0 +1,2 @@
:mod:`zoneinfo`: fix a crash when instantiating :class:`~zoneinfo.ZoneInfo`
objects for which the internal class-level cache is inconsistent.

View file

@ -335,6 +335,7 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key)
return NULL;
}
((PyZoneInfo_ZoneInfo *)tmp)->source = SOURCE_CACHE;
instance =
PyObject_CallMethod(weak_cache, "setdefault", "OO", key, tmp);
Py_DECREF(tmp);
@ -342,7 +343,15 @@ zoneinfo_ZoneInfo_impl(PyTypeObject *type, PyObject *key)
Py_DECREF(weak_cache);
return NULL;
}
((PyZoneInfo_ZoneInfo *)instance)->source = SOURCE_CACHE;
}
if (!PyObject_TypeCheck(instance, type)) {
PyErr_Format(PyExc_RuntimeError,
"Unexpected instance of %T in %s weak cache for key %R",
instance, _PyType_Name(type), key);
Py_DECREF(instance);
Py_DECREF(weak_cache);
return NULL;
}
update_strong_cache(state, type, key, instance);