From a7b8768e56eb7f3a0fa90c8b45d8679c889d06cb Mon Sep 17 00:00:00 2001 From: CPython Developers <> Date: Sun, 5 Mar 2023 01:52:22 +0900 Subject: [PATCH 1/2] Update test_baseexception.py from cpython 3.11.2 --- Lib/test/test_baseexception.py | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_baseexception.py b/Lib/test/test_baseexception.py index f1da03ebe4..e4cbd6b6f8 100644 --- a/Lib/test/test_baseexception.py +++ b/Lib/test/test_baseexception.py @@ -28,8 +28,9 @@ def test_inheritance(self): except TypeError: pass - inheritance_tree = open(os.path.join(os.path.split(__file__)[0], - 'exception_hierarchy.txt')) + inheritance_tree = open( + os.path.join(os.path.split(__file__)[0], 'exception_hierarchy.txt'), + encoding="utf-8") try: superclass_name = inheritance_tree.readline().rstrip() try: @@ -43,7 +44,7 @@ def test_inheritance(self): last_depth = 0 for exc_line in inheritance_tree: exc_line = exc_line.rstrip() - depth = exc_line.rindex('-') + depth = exc_line.rindex('─') exc_name = exc_line[depth+2:] # Slice past space if '(' in exc_name: paren_index = exc_name.index('(') @@ -117,6 +118,31 @@ def test_interface_no_arg(self): [repr(exc), exc.__class__.__name__ + '()']) self.interface_test_driver(results) + def test_setstate_refcount_no_crash(self): + # gh-97591: Acquire strong reference before calling tp_hash slot + # in PyObject_SetAttr. + import gc + d = {} + class HashThisKeyWillClearTheDict(str): + def __hash__(self) -> int: + d.clear() + return super().__hash__() + class Value(str): + pass + exc = Exception() + + d[HashThisKeyWillClearTheDict()] = Value() # refcount of Value() is 1 now + + # Exception.__setstate__ should aquire a strong reference of key and + # value in the dict. Otherwise, Value()'s refcount would go below + # zero in the tp_hash call in PyObject_SetAttr(), and it would cause + # crash in GC. + exc.__setstate__(d) # __hash__() is called again here, clearing the dict. + + # This GC would crash if the refcount of Value() goes below zero. + gc.collect() + + class UsageTests(unittest.TestCase): """Test usage of exceptions""" From 9c10d4aa3f6c50e90e7db6b77cd6dd3b0d43dd17 Mon Sep 17 00:00:00 2001 From: LYK Date: Sun, 5 Mar 2023 03:20:53 +0900 Subject: [PATCH 2/2] Mark failing tests of test_baseexception. --- Lib/test/test_baseexception.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/test/test_baseexception.py b/Lib/test/test_baseexception.py index e4cbd6b6f8..2be9405bcc 100644 --- a/Lib/test/test_baseexception.py +++ b/Lib/test/test_baseexception.py @@ -18,6 +18,8 @@ def verify_instance_interface(self, ins): "%s missing %s attribute" % (ins.__class__.__name__, attr)) + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_inheritance(self): # Make sure the inheritance hierarchy matches the documentation exc_set = set() @@ -118,6 +120,8 @@ def test_interface_no_arg(self): [repr(exc), exc.__class__.__name__ + '()']) self.interface_test_driver(results) + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_setstate_refcount_no_crash(self): # gh-97591: Acquire strong reference before calling tp_hash slot # in PyObject_SetAttr.