From: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> Date: Tue, 1 Jul 2025 15:19:39 +0000 (+0200) Subject: [3.13] gh-87298: Add tests for find_in_strong_cache() bug in _zoneinfo (GH-24829... X-Git-Tag: v3.13.6~145 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=da2c4ef7eb4ec2bf7615073b6636b9192222d92b;p=thirdparty%2FPython%2Fcpython.git [3.13] gh-87298: Add tests for find_in_strong_cache() bug in _zoneinfo (GH-24829) (GH-136182) (cherry picked from commit 12ce16bc134a602d2ac8acde86ae69f70183cb9f) Co-authored-by: Zackery Spytz Co-authored-by: Paul Ganssle Co-authored-by: Serhiy Storchaka --- diff --git a/Lib/test/test_zoneinfo/test_zoneinfo.py b/Lib/test/test_zoneinfo/test_zoneinfo.py index f687f29c2224..d51736e34c60 100644 --- a/Lib/test/test_zoneinfo/test_zoneinfo.py +++ b/Lib/test/test_zoneinfo/test_zoneinfo.py @@ -57,6 +57,10 @@ def tearDownModule(): shutil.rmtree(TEMP_DIR) +class CustomError(Exception): + pass + + class TzPathUserMixin: """ Adds a setUp() and tearDown() to make TZPATH manipulations thread-safe. @@ -403,6 +407,25 @@ class ZoneInfoTest(TzPathUserMixin, ZoneInfoTestBase): self.assertEqual(t.utcoffset(), offset.utcoffset) self.assertEqual(t.dst(), offset.dst) + def test_cache_exception(self): + class Incomparable(str): + eq_called = False + def __eq__(self, other): + self.eq_called = True + raise CustomError + __hash__ = str.__hash__ + + key = "America/Los_Angeles" + tz1 = self.klass(key) + key = Incomparable(key) + try: + tz2 = self.klass(key) + except CustomError: + self.assertTrue(key.eq_called) + else: + self.assertFalse(key.eq_called) + self.assertIs(tz2, tz1) + class CZoneInfoTest(ZoneInfoTest): module = c_zoneinfo @@ -1506,6 +1529,26 @@ class ZoneInfoCacheTest(TzPathUserMixin, ZoneInfoTestBase): self.assertIsNot(dub0, dub1) self.assertIs(tok0, tok1) + def test_clear_cache_refleak(self): + class Stringy(str): + allow_comparisons = True + def __eq__(self, other): + if not self.allow_comparisons: + raise CustomError + return super().__eq__(other) + __hash__ = str.__hash__ + + key = Stringy("America/Los_Angeles") + self.klass(key) + key.allow_comparisons = False + try: + # Note: This is try/except rather than assertRaises because + # there is no guarantee that the key is even still in the cache, + # or that the key for the cache is the original `key` object. + self.klass.clear_cache(only_keys="America/Los_Angeles") + except CustomError: + pass + class CZoneInfoCacheTest(ZoneInfoCacheTest): module = c_zoneinfo