Skip to content

gh-111178: fix UBSan failures for _PyExecutorObject #131610

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 24, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions Python/optimizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

#define MAX_EXECUTORS_SIZE 256

#define _PyExecutorObject_CAST(op) ((_PyExecutorObject *)(op))

static bool
has_space_for_executor(PyCodeObject *code, _Py_CODEUNIT *instr)
{
Expand Down Expand Up @@ -199,11 +201,12 @@ get_oparg(PyObject *self, PyObject *Py_UNUSED(ignored))

///////////////////// Experimental UOp Optimizer /////////////////////

static int executor_clear(_PyExecutorObject *executor);
static int executor_clear(PyObject *executor);
static void unlink_executor(_PyExecutorObject *executor);

static void
uop_dealloc(_PyExecutorObject *self) {
uop_dealloc(PyObject *op) {
_PyExecutorObject *self = _PyExecutorObject_CAST(op);
_PyObject_GC_UNTRACK(self);
assert(self->vm_data.code == NULL);
unlink_executor(self);
Expand Down Expand Up @@ -260,15 +263,17 @@ _PyUOpPrint(const _PyUOpInstruction *uop)
#endif

static Py_ssize_t
uop_len(_PyExecutorObject *self)
uop_len(PyObject *op)
{
_PyExecutorObject *self = _PyExecutorObject_CAST(op);
return self->code_size;
}

static PyObject *
uop_item(_PyExecutorObject *self, Py_ssize_t index)
uop_item(PyObject *op, Py_ssize_t index)
{
Py_ssize_t len = uop_len(self);
_PyExecutorObject *self = _PyExecutorObject_CAST(op);
Py_ssize_t len = uop_len(op);
if (index < 0 || index >= len) {
PyErr_SetNone(PyExc_IndexError);
return NULL;
Expand Down Expand Up @@ -304,14 +309,14 @@ uop_item(_PyExecutorObject *self, Py_ssize_t index)
}

PySequenceMethods uop_as_sequence = {
.sq_length = (lenfunc)uop_len,
.sq_item = (ssizeargfunc)uop_item,
.sq_length = uop_len,
.sq_item = uop_item,
};

static int
executor_traverse(PyObject *o, visitproc visit, void *arg)
{
_PyExecutorObject *executor = (_PyExecutorObject *)o;
_PyExecutorObject *executor = _PyExecutorObject_CAST(o);
for (uint32_t i = 0; i < executor->exit_count; i++) {
Py_VISIT(executor->exits[i].executor);
}
Expand All @@ -325,7 +330,7 @@ get_jit_code(PyObject *self, PyObject *Py_UNUSED(ignored))
PyErr_SetString(PyExc_RuntimeError, "JIT support not enabled.");
return NULL;
#else
_PyExecutorObject *executor = (_PyExecutorObject *)self;
_PyExecutorObject *executor = _PyExecutorObject_CAST(self);
if (executor->jit_code == NULL || executor->jit_size == 0) {
Py_RETURN_NONE;
}
Expand Down Expand Up @@ -353,11 +358,11 @@ PyTypeObject _PyUOpExecutor_Type = {
.tp_basicsize = offsetof(_PyExecutorObject, exits),
.tp_itemsize = 1,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_HAVE_GC,
.tp_dealloc = (destructor)uop_dealloc,
.tp_dealloc = uop_dealloc,
.tp_as_sequence = &uop_as_sequence,
.tp_methods = uop_executor_methods,
.tp_traverse = executor_traverse,
.tp_clear = (inquiry)executor_clear,
.tp_clear = executor_clear,
.tp_is_gc = executor_is_gc,
};

Expand Down Expand Up @@ -1422,8 +1427,9 @@ _Py_ExecutorDetach(_PyExecutorObject *executor)
}

static int
executor_clear(_PyExecutorObject *executor)
executor_clear(PyObject *op)
{
_PyExecutorObject *executor = _PyExecutorObject_CAST(op);
if (!executor->vm_data.valid) {
return 0;
}
Expand Down Expand Up @@ -1479,7 +1485,7 @@ _Py_Executors_InvalidateDependency(PyInterpreterState *interp, void *obj, int is
exec = next;
}
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(invalidate); i++) {
_PyExecutorObject *exec = (_PyExecutorObject *)PyList_GET_ITEM(invalidate, i);
PyObject *exec = PyList_GET_ITEM(invalidate, i);
executor_clear(exec);
if (is_invalidation) {
OPT_STAT_INC(executors_invalidated);
Expand All @@ -1506,7 +1512,7 @@ _Py_Executors_InvalidateAll(PyInterpreterState *interp, int is_invalidation)
_PyCode_Clear_Executors(executor->vm_data.code);
}
else {
executor_clear(executor);
executor_clear((PyObject *)executor);
}
if (is_invalidation) {
OPT_STAT_INC(executors_invalidated);
Expand Down Expand Up @@ -1540,7 +1546,7 @@ _Py_Executors_InvalidateCold(PyInterpreterState *interp)
exec = next;
}
for (Py_ssize_t i = 0; i < PyList_GET_SIZE(invalidate); i++) {
_PyExecutorObject *exec = (_PyExecutorObject *)PyList_GET_ITEM(invalidate, i);
PyObject *exec = PyList_GET_ITEM(invalidate, i);
executor_clear(exec);
}
Py_DECREF(invalidate);
Expand Down
Loading