diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2021-05-21 22:50:11 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-21 22:50:11 (GMT) |
commit | 50b0d148a68072292832eb69bdf1815b8059355f (patch) | |
tree | fa1d73efadcf398b0c6dd33b364e13841d66b8a0 /Lib/test/test_gc.py | |
parent | 856958d0e750a62bd5e6a231c3ed67aa0db32e11 (diff) | |
download | cpython-50b0d148a68072292832eb69bdf1815b8059355f.zip cpython-50b0d148a68072292832eb69bdf1815b8059355f.tar.gz cpython-50b0d148a68072292832eb69bdf1815b8059355f.tar.bz2 |
bpo-44184: Fix subtype_dealloc() for freed type (GH-26274) (GH-26290)
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.
(cherry picked from commit 615069eb08494d089bf24e43547fbc482ed699b8)
Co-authored-by: Victor Stinner <vstinner@python.org>
Co-authored-by: Victor Stinner <vstinner@python.org>
Diffstat (limited to 'Lib/test/test_gc.py')
-rw-r--r-- | Lib/test/test_gc.py | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index ee4fe49..1528cf6 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -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 |