You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
BUG: out reference leak in PyUFunc_Accumulate and PyUFunc_Reduceat on type resolution failure #31691
In both PyUFunc_Accumulate and PyUFunc_Reduceat, the out argument is INCREF'd early in the function, but when reducelike_promote_and_resolve fails immediately after, the code does return NULL directly — bypassing the fail label where Py_XDECREF(out) is located. This leaks the reference to out.
/* Take a reference to out for later returning */Py_XINCREF(out); // line ~2745 / ~3168PyArray_Descr*descrs[3];
PyArrayMethodObject*ufuncimpl=reducelike_promote_and_resolve(ufunc,
arr, out, signature, NPY_TRUE, descrs, NPY_UNSAFE_CASTING,
"accumulate"); // or "reduceat"if (ufuncimpl==NULL) {
returnNULL; // BUG: out's INCREF never balanced
}
Further down the function, the fail: label correctly does Py_XDECREF(out), but the early return NULL bypasses it.
Impact
Every time accumulate() or reduceat() is called with an out argument and type resolution fails (e.g., incompatible dtypes), the out array leaks a reference. Over repeated calls, this prevents the array from being garbage collected.
Suggested Fix
Change return NULL to goto fail in both locations:
if (ufuncimpl==NULL) {
goto fail;
}
This ensures the fail label's cleanup runs, which includes Py_XDECREF(out).
Environment
NumPy: current main branch
Affected: numpy.ufunc.accumulate() and numpy.ufunc.reduceat() with out argument on type resolution failure
I was reading the whole reducer code paths in the last few days to understand it and I also thought about this issue myself. @mattip I think failures to resolve the dtype when out is provided will hit this so something like this will make the ref count of out be 10K because it can't resolve the output being U5.
but goto fail is not right solution, it does cleanup of uninitialized state and leads to a bus error crash. So either Py_XDECREF(out) before return NULL or moving the uninitialized state to initialized to NULL so that Py_XDECREF in the fail block is safe is the solution I think.
I think it's low-priority anyways cause hopefully nobody tries so hard to fail the dtype resolution like my snippet does 🤣 so the leak is not important in the real world most likely.
changed the title [-][BUG] out reference leak in PyUFunc_Accumulate and PyUFunc_Reduceat on type resolution failure[/-][+]BUG: out reference leak in PyUFunc_Accumulate and PyUFunc_Reduceat on type resolution failure[/+]on Jun 22, 2026
Activity
mattip commentedon Jun 19, 2026
Is this theoretical or is there a reproducer?
ikrommyd commentedon Jun 19, 2026
I was reading the whole reducer code paths in the last few days to understand it and I also thought about this issue myself.
@mattip I think failures to resolve the dtype when
outis provided will hit this so something like this will make the ref count of out be 10K because it can't resolve the output beingU5.but
goto failis not right solution, it does cleanup of uninitialized state and leads to a bus error crash. So eitherPy_XDECREF(out)beforereturn NULLor moving the uninitialized state to initialized to NULL so thatPy_XDECREFin thefailblock is safe is the solution I think.I think it's low-priority anyways cause hopefully nobody tries so hard to fail the dtype resolution like my snippet does 🤣 so the leak is not important in the real world most likely.
[-][BUG] out reference leak in PyUFunc_Accumulate and PyUFunc_Reduceat on type resolution failure[/-][+]BUG: out reference leak in PyUFunc_Accumulate and PyUFunc_Reduceat on type resolution failure[/+]