bpo-44184: Fix subtype_dealloc() for freed type (GH-26274)

Fix a crash at Python exit when a deallocator function removes the
last strong reference to a heap type.

Don't read type memory after calling basedealloc() since
basedealloc() can deallocate the type and free its memory.

_PyMem_IsPtrFreed() argument is now constant.
This commit is contained in:
Victor Stinner 2021-05-21 19:19:54 +02:00 committed by GitHub
parent 642fdfdc04
commit 615069eb08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 4 deletions

View file

@ -1361,6 +1361,34 @@ class GCTogglingTests(unittest.TestCase):
# empty __dict__.
self.assertEqual(x, None)
class PythonFinalizationTests(unittest.TestCase):
def test_ast_fini(self):
# bpo-44184: Regression test for subtype_dealloc() when deallocating
# an AST instance also destroy its AST type: subtype_dealloc() must
# not access the type memory after deallocating the instance, since
# the type memory can be freed as well. The test is also related to
# _PyAST_Fini() which clears references to AST types.
code = textwrap.dedent("""
import ast
import codecs
# Small AST tree to keep their AST types alive
tree = ast.parse("def f(x, y): return 2*x-y")
x = [tree]
x.append(x)
# Put the cycle somewhere to survive until the last GC collection.
# Codec search functions are only cleared at the end of
# interpreter_clear().
def search_func(encoding):
return None
search_func.a = x
codecs.register(search_func)
""")
assert_python_ok("-c", code)
def test_main():
enabled = gc.isenabled()
gc.disable()
@ -1370,7 +1398,11 @@ def test_main():
try:
gc.collect() # Delete 2nd generation garbage
run_unittest(GCTests, GCTogglingTests, GCCallbackTests)
run_unittest(
GCTests,
GCCallbackTests,
GCTogglingTests,
PythonFinalizationTests)
finally:
gc.set_debug(debug)
# test gc.enable() even if GC is disabled by default