
To: python-checkins@python.org Subject: Clear weakrefs in garbage found by the GC (GH-16495) (#16499) Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 https://github.com/python/cpython/commit/92ca515ee1efbdc51678e12d105ad642c9b... cc13 commit: 92ca515ee1efbdc51678e12d105ad642c9b9cc13 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.co= m> committer: =C5=81ukasz Langa <lukasz@langa.pl> date: 2019-09-30T19:27:46+02:00 summary: Clear weakrefs in garbage found by the GC (GH-16495) (#16499) Fix a bug due to the interaction of weakrefs and the cyclic garbage collector. We must clear any weakrefs in garbage in order to prevent their callbacks from executing and causing a crash. (cherry picked from commit bcda460baf25062ab68622b3f043f52b9db4d21d) Co-authored-by: Neil Schemenauer <nas-github@arctrix.com> files: A Misc/NEWS.d/next/Core and Builtins/2019-09-30-09-33-21.bpo-38006.UYlJum.rst M Modules/gcmodule.c diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-09-30-09-33-21.bpo-38006= .UYlJum.rst b/Misc/NEWS.d/next/Core and Builtins/2019-09-30-09-33-21.bpo-3800= 6.UYlJum.rst new file mode 100644 index 000000000000..c2dafae0afab --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2019-09-30-09-33-21.bpo-38006.UYlJum= .rst=09 @@ -0,0 +1,3 @@ +Fix a bug due to the interaction of weakrefs and the cyclic garbage +collector. We must clear any weakrefs in garbage in order to prevent their +callbacks from executing and causing a crash. diff --git a/Modules/gcmodule.c b/Modules/gcmodule.c index b2ee56623cd4..8bdbafef167e 100644 --- a/Modules/gcmodule.c +++ b/Modules/gcmodule.c @@ -678,6 +678,21 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) op =3D FROM_GC(gc); next =3D GC_NEXT(gc); =20 + if (PyWeakref_Check(op)) { + /* A weakref inside the unreachable set must be cleared. If we + * allow its callback to execute inside delete_garbage(), it + * could expose objects that have tp_clear already called on + * them. Or, it could resurrect unreachable objects. One way + * this can happen is if some container objects do not implement + * tp_traverse. Then, wr_object can be outside the unreachable + * set but can be deallocated as a result of breaking the + * reference cycle. If we don't clear the weakref, the callback + * will run and potentially cause a crash. See bpo-38006 for + * one example. + */ + _PyWeakref_ClearRef((PyWeakReference *)op); + } + if (! PyType_SUPPORTS_WEAKREFS(Py_TYPE(op))) continue; =20 @@ -733,6 +748,8 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old) * is moved to wrcb_to_call in this case. */ if (gc_is_collecting(AS_GC(wr))) { + /* it should already have been cleared above */ + assert(wr->wr_object =3D=3D Py_None); continue; } =20
participants (1)
-
Łukasz Langa