Skip to content

Commit ab7971d

Browse files
authored
Merge pull request #4624 from dalinaum/test_baseexception
Update test_baseexception.py from cpython 3.11.2
2 parents 298b169 + 9c10d4a commit ab7971d

File tree

1 file changed

+33
-3
lines changed

1 file changed

+33
-3
lines changed

Lib/test/test_baseexception.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ def verify_instance_interface(self, ins):
1818
"%s missing %s attribute" %
1919
(ins.__class__.__name__, attr))
2020

21+
# TODO: RUSTPYTHON
22+
@unittest.expectedFailure
2123
def test_inheritance(self):
2224
# Make sure the inheritance hierarchy matches the documentation
2325
exc_set = set()
@@ -28,8 +30,9 @@ def test_inheritance(self):
2830
except TypeError:
2931
pass
3032

31-
inheritance_tree = open(os.path.join(os.path.split(__file__)[0],
32-
'exception_hierarchy.txt'))
33+
inheritance_tree = open(
34+
os.path.join(os.path.split(__file__)[0], 'exception_hierarchy.txt'),
35+
encoding="utf-8")
3336
try:
3437
superclass_name = inheritance_tree.readline().rstrip()
3538
try:
@@ -43,7 +46,7 @@ def test_inheritance(self):
4346
last_depth = 0
4447
for exc_line in inheritance_tree:
4548
exc_line = exc_line.rstrip()
46-
depth = exc_line.rindex('-')
49+
depth = exc_line.rindex('')
4750
exc_name = exc_line[depth+2:] # Slice past space
4851
if '(' in exc_name:
4952
paren_index = exc_name.index('(')
@@ -117,6 +120,33 @@ def test_interface_no_arg(self):
117120
[repr(exc), exc.__class__.__name__ + '()'])
118121
self.interface_test_driver(results)
119122

123+
# TODO: RUSTPYTHON
124+
@unittest.expectedFailure
125+
def test_setstate_refcount_no_crash(self):
126+
# gh-97591: Acquire strong reference before calling tp_hash slot
127+
# in PyObject_SetAttr.
128+
import gc
129+
d = {}
130+
class HashThisKeyWillClearTheDict(str):
131+
def __hash__(self) -> int:
132+
d.clear()
133+
return super().__hash__()
134+
class Value(str):
135+
pass
136+
exc = Exception()
137+
138+
d[HashThisKeyWillClearTheDict()] = Value() # refcount of Value() is 1 now
139+
140+
# Exception.__setstate__ should aquire a strong reference of key and
141+
# value in the dict. Otherwise, Value()'s refcount would go below
142+
# zero in the tp_hash call in PyObject_SetAttr(), and it would cause
143+
# crash in GC.
144+
exc.__setstate__(d) # __hash__() is called again here, clearing the dict.
145+
146+
# This GC would crash if the refcount of Value() goes below zero.
147+
gc.collect()
148+
149+
120150
class UsageTests(unittest.TestCase):
121151

122152
"""Test usage of exceptions"""

0 commit comments

Comments
 (0)