From 1ce322e453c79cdc0f0f128e167272290551f75f Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Wed, 25 Sep 2024 18:32:44 -0400 Subject: [PATCH 1/4] Add NULL check for capsule_traverse --- Objects/capsule.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Objects/capsule.c b/Objects/capsule.c index 555979dab2b789..28965e0f21b7a0 100644 --- a/Objects/capsule.c +++ b/Objects/capsule.c @@ -317,10 +317,14 @@ static int capsule_traverse(PyCapsule *capsule, visitproc visit, void *arg) { // Capsule object is only tracked by the GC - // if _PyCapsule_SetTraverse() is called - assert(capsule->traverse_func != NULL); + // if _PyCapsule_SetTraverse() is called, but + // this can still be manually triggered by gc.get_referents() + + if (capsule->traverse_func != NULL) { + return capsule->traverse_func((PyObject*)capsule, visit, arg); + } - return capsule->traverse_func((PyObject*)capsule, visit, arg); + return 0; } From 26b4e4c3f5410abafcc42cb664771348076e4c29 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Wed, 25 Sep 2024 18:34:52 -0400 Subject: [PATCH 2/4] Add NEWS entry. --- .../next/Library/2024-09-25-18-34-48.gh-issue-124538.nXZk4R.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2024-09-25-18-34-48.gh-issue-124538.nXZk4R.rst diff --git a/Misc/NEWS.d/next/Library/2024-09-25-18-34-48.gh-issue-124538.nXZk4R.rst b/Misc/NEWS.d/next/Library/2024-09-25-18-34-48.gh-issue-124538.nXZk4R.rst new file mode 100644 index 00000000000000..33ae037ae56b0b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-25-18-34-48.gh-issue-124538.nXZk4R.rst @@ -0,0 +1 @@ +Fixed crash when using :func:`gc.get_referents` on a capsule object. From dcd0593908c2dd3fe49e4f06da2ead0ff41bbd9a Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Wed, 25 Sep 2024 18:45:27 -0400 Subject: [PATCH 3/4] Add test. --- Lib/test/test_gc.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index 906f9884d6792f..d00ddb3942127a 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -1048,6 +1048,24 @@ class Z: callback.assert_not_called() gc.enable() + @cpython_only + def test_get_referents_on_capsule(self): + # See GH-124538 + import _datetime + import _socket + untracked_capsule = _datetime.datetime_CAPI + tracked_capsule = _socket.CAPI + + # For whoever sees this in the future: if this is failing + # after making datetime's capsule tracked, that's fine -- this isn't something + # users are relying on. Just find a different capsule that is untracked. + self.assertFalse(gc.is_tracked(untracked_capsule)) + self.assertTrue(gc.is_tracked(tracked_capsule)) + + self.assertEqual(len(gc.get_referents(untracked_capsule)), 0) + gc.get_referents(tracked_capsule) + + class IncrementalGCTests(unittest.TestCase): From e8b7e4757fe0f6eb1642d2388ac9da171a4f7ad4 Mon Sep 17 00:00:00 2001 From: Peter Bierma Date: Thu, 26 Sep 2024 06:04:12 -0400 Subject: [PATCH 4/4] Update test_gc.py Co-authored-by: Victor Stinner --- Lib/test/test_gc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py index d00ddb3942127a..bb7df1f5cfa7f7 100644 --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -1050,7 +1050,7 @@ class Z: @cpython_only def test_get_referents_on_capsule(self): - # See GH-124538 + # gh-124538: Calling gc.get_referents() on an untracked capsule must not crash. import _datetime import _socket untracked_capsule = _datetime.datetime_CAPI