Skip to content

Commit 4efe397

Browse files
authoredMar 24, 2025··
gh-111178: fix UBSan failures for anextawaitableobject (#131609)
1 parent b3319fe commit 4efe397

File tree

1 file changed

+29
-15
lines changed

1 file changed

+29
-15
lines changed
 

‎Objects/iterobject.c

+29-15
Original file line numberDiff line numberDiff line change
@@ -315,18 +315,22 @@ typedef struct {
315315
PyObject *default_value;
316316
} anextawaitableobject;
317317

318+
#define anextawaitableobject_CAST(op) ((anextawaitableobject *)(op))
319+
318320
static void
319-
anextawaitable_dealloc(anextawaitableobject *obj)
321+
anextawaitable_dealloc(PyObject *op)
320322
{
323+
anextawaitableobject *obj = anextawaitableobject_CAST(op);
321324
_PyObject_GC_UNTRACK(obj);
322325
Py_XDECREF(obj->wrapped);
323326
Py_XDECREF(obj->default_value);
324327
PyObject_GC_Del(obj);
325328
}
326329

327330
static int
328-
anextawaitable_traverse(anextawaitableobject *obj, visitproc visit, void *arg)
331+
anextawaitable_traverse(PyObject *op, visitproc visit, void *arg)
329332
{
333+
anextawaitableobject *obj = anextawaitableobject_CAST(op);
330334
Py_VISIT(obj->wrapped);
331335
Py_VISIT(obj->default_value);
332336
return 0;
@@ -363,7 +367,7 @@ anextawaitable_getiter(anextawaitableobject *obj)
363367
}
364368

365369
static PyObject *
366-
anextawaitable_iternext(anextawaitableobject *obj)
370+
anextawaitable_iternext(PyObject *op)
367371
{
368372
/* Consider the following class:
369373
*
@@ -385,6 +389,7 @@ anextawaitable_iternext(anextawaitableobject *obj)
385389
* Then `await anext(gen)` can just call
386390
* gen.__anext__().__next__()
387391
*/
392+
anextawaitableobject *obj = anextawaitableobject_CAST(op);
388393
PyObject *awaitable = anextawaitable_getiter(obj);
389394
if (awaitable == NULL) {
390395
return NULL;
@@ -403,11 +408,14 @@ anextawaitable_iternext(anextawaitableobject *obj)
403408

404409

405410
static PyObject *
406-
anextawaitable_proxy(anextawaitableobject *obj, char *meth, PyObject *arg) {
411+
anextawaitable_proxy(anextawaitableobject *obj, char *meth, PyObject *arg)
412+
{
407413
PyObject *awaitable = anextawaitable_getiter(obj);
408414
if (awaitable == NULL) {
409415
return NULL;
410416
}
417+
// 'arg' may be a tuple (if coming from a METH_VARARGS method)
418+
// or a single object (if coming from a METH_O method).
411419
PyObject *ret = PyObject_CallMethod(awaitable, meth, "O", arg);
412420
Py_DECREF(awaitable);
413421
if (ret != NULL) {
@@ -427,20 +435,26 @@ anextawaitable_proxy(anextawaitableobject *obj, char *meth, PyObject *arg) {
427435

428436

429437
static PyObject *
430-
anextawaitable_send(anextawaitableobject *obj, PyObject *arg) {
438+
anextawaitable_send(PyObject *op, PyObject *arg)
439+
{
440+
anextawaitableobject *obj = anextawaitableobject_CAST(op);
431441
return anextawaitable_proxy(obj, "send", arg);
432442
}
433443

434444

435445
static PyObject *
436-
anextawaitable_throw(anextawaitableobject *obj, PyObject *arg) {
437-
return anextawaitable_proxy(obj, "throw", arg);
446+
anextawaitable_throw(PyObject *op, PyObject *args)
447+
{
448+
anextawaitableobject *obj = anextawaitableobject_CAST(op);
449+
return anextawaitable_proxy(obj, "throw", args);
438450
}
439451

440452

441453
static PyObject *
442-
anextawaitable_close(anextawaitableobject *obj, PyObject *arg) {
443-
return anextawaitable_proxy(obj, "close", arg);
454+
anextawaitable_close(PyObject *op, PyObject *args)
455+
{
456+
anextawaitableobject *obj = anextawaitableobject_CAST(op);
457+
return anextawaitable_proxy(obj, "close", args);
444458
}
445459

446460

@@ -464,9 +478,9 @@ PyDoc_STRVAR(close_doc,
464478

465479

466480
static PyMethodDef anextawaitable_methods[] = {
467-
{"send",(PyCFunction)anextawaitable_send, METH_O, send_doc},
468-
{"throw",(PyCFunction)anextawaitable_throw, METH_VARARGS, throw_doc},
469-
{"close",(PyCFunction)anextawaitable_close, METH_VARARGS, close_doc},
481+
{"send", anextawaitable_send, METH_O, send_doc},
482+
{"throw", anextawaitable_throw, METH_VARARGS, throw_doc},
483+
{"close", anextawaitable_close, METH_VARARGS, close_doc},
470484
{NULL, NULL} /* Sentinel */
471485
};
472486

@@ -484,7 +498,7 @@ PyTypeObject _PyAnextAwaitable_Type = {
484498
sizeof(anextawaitableobject), /* tp_basicsize */
485499
0, /* tp_itemsize */
486500
/* methods */
487-
(destructor)anextawaitable_dealloc, /* tp_dealloc */
501+
anextawaitable_dealloc, /* tp_dealloc */
488502
0, /* tp_vectorcall_offset */
489503
0, /* tp_getattr */
490504
0, /* tp_setattr */
@@ -501,12 +515,12 @@ PyTypeObject _PyAnextAwaitable_Type = {
501515
0, /* tp_as_buffer */
502516
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
503517
0, /* tp_doc */
504-
(traverseproc)anextawaitable_traverse, /* tp_traverse */
518+
anextawaitable_traverse, /* tp_traverse */
505519
0, /* tp_clear */
506520
0, /* tp_richcompare */
507521
0, /* tp_weaklistoffset */
508522
PyObject_SelfIter, /* tp_iter */
509-
(unaryfunc)anextawaitable_iternext, /* tp_iternext */
523+
anextawaitable_iternext, /* tp_iternext */
510524
anextawaitable_methods, /* tp_methods */
511525
};
512526

0 commit comments

Comments
 (0)
Please sign in to comment.