Skip to content

Commit 9941183

Browse files
committed
gh-108240: _PyCapsule_SetTraverse() rejects NULL callbacks
1 parent c163d7f commit 9941183

File tree

1 file changed

+19
-15
lines changed

1 file changed

+19
-15
lines changed

Objects/capsule.c

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
7171
capsule->destructor = destructor;
7272
capsule->traverse_func = NULL;
7373
capsule->clear_func = NULL;
74-
// Only track the capsule if _PyCapsule_SetTraverse() is called
74+
// Only track the object by the GC when _PyCapsule_SetTraverse() is called
7575

7676
return (PyObject *)capsule;
7777
}
@@ -204,8 +204,14 @@ _PyCapsule_SetTraverse(PyObject *op, traverseproc traverse_func, inquiry clear_f
204204
}
205205
PyCapsule *capsule = (PyCapsule *)op;
206206

207-
if (!PyObject_GC_IsTracked(op)) {
208-
PyObject_GC_Track(op);
207+
if (traverse_func == NULL || clear_func == NULL) {
208+
PyErr_SetString(PyExc_ValueError,
209+
"_PyCapsule_SetTraverse() called with NULL callback");
210+
return -1;
211+
}
212+
213+
if (!_PyObject_GC_IS_TRACKED(op)) {
214+
_PyObject_GC_TRACK(op);
209215
}
210216

211217
capsule->traverse_func = traverse_func;
@@ -306,24 +312,22 @@ capsule_repr(PyObject *o)
306312
static int
307313
capsule_traverse(PyCapsule *capsule, visitproc visit, void *arg)
308314
{
309-
if (capsule->traverse_func) {
310-
return capsule->traverse_func((PyObject*)capsule, visit, arg);
311-
}
312-
else {
313-
return 0;
314-
}
315+
// Capsule object is only tracked by the GC
316+
// if _PyCapsule_SetTraverse() is called
317+
assert(capsule->traverse_func != NULL);
318+
319+
return capsule->traverse_func((PyObject*)capsule, visit, arg);
315320
}
316321

317322

318323
static int
319324
capsule_clear(PyCapsule *capsule)
320325
{
321-
if (capsule->clear_func) {
322-
return capsule->clear_func((PyObject*)capsule);
323-
}
324-
else {
325-
return 0;
326-
}
326+
// Capsule object is only tracked by the GC
327+
// if _PyCapsule_SetTraverse() is called
328+
assert(capsule->clear_func != NULL);
329+
330+
return capsule->clear_func((PyObject*)capsule);
327331
}
328332

329333

0 commit comments

Comments
 (0)