8000 BUG: do not decref borrowed refs for extobj and axes by mhvk · Pull Request #11244 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: do not decref borrowed refs for extobj and axes #11244

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
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 fil 8000 es.
Loading
Diff view
Diff view
39 changes: 25 additions & 14 deletions numpy/core/src/umath/ufunc_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,8 +555,14 @@ ufunc_get_name_cstr(PyUFuncObject *ufunc) {
* Parses the positional and keyword arguments for a generic ufunc call.
*
* Note that if an error is returned, the caller must free the
* non-zero references in out_op. This
* function does not do its own clean-up.
* non-zero references in out_op. This function does not do its own clean-up.
*
* Note also that some of the outputs for keyword arguments contain
* borrowed references, while others are new references. In particular,
* out_extobj: borrowed ref.
* out_typetup: new ref.
* out_wheremask: new ref.
* out_axes: borrowed ref.
Copy link
Member
@eric-wieser eric-wieser Jun 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about out_op? nevermind, I see that's above

I'd be inclined to put these on the same line as the parameter definitions, to reduce the chance of the comments going out of sync

*/
static int
get_ufunc_arguments(PyUFuncObject *ufunc,
Expand Down Expand Up @@ -851,7 +857,7 @@ get_ufunc_arguments(PyUFuncObject *ufunc,
if (dtype != NULL) {
if (*out_typetup != NULL) {
PyErr_SetString(PyExc_RuntimeError,
"cannot specify both 'sig' and 'dtype'");
"cannot specify both 'signature' and 'dtype'");
goto fail;
}
*out_typetup = Py_BuildValue("(N)", dtype);
Expand Down Expand Up @@ -965,7 +971,7 @@ get_ufunc_arguments(PyUFuncObject *ufunc,
}
if (*out_typetup != NULL) {
PyErr_SetString(PyExc_RuntimeError,
"cannot specify both 'sig' and 'dtype'");
"cannot specify both 'signature' and 'dtype'");
goto fail;
}
*out_typetup = value;
Expand Down Expand Up @@ -1027,18 +1033,19 @@ get_ufunc_arguments(PyUFuncObject *ufunc,

fail:
Py_XDECREF(str_key_obj);
Py_XDECREF(*out_extobj);
*out_extobj = NULL;
/*
* Set output kwargs to NULL, XDECREF'ing those that were not borrowed.
*/
Py_XDECREF(*out_typetup);
*out_typetup = NULL;
if (out_axes != NULL) {
Py_XDECREF(*out_axes);
*out_axes = NULL;
}
*out_extobj = NULL;
if (out_wheremask != NULL) {
Py_XDECREF(*out_wheremask);
*out_wheremask = NULL;
}
if (out_axes != NULL) {
*out_axes = NULL;
}
return -1;
}

Expand Down Expand Up @@ -2239,8 +2246,10 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
NPY_ORDER order = NPY_KEEPORDER;
/* Use the default assignment casting rule */
NPY_CASTING casting = NPY_DEFAULT_ASSIGN_CASTING;
/* When provided, extobj, typetup, and axes contain borrowed references */
PyObject *extobj = NULL, *type_tup = NULL, *axes = NULL;
/* When provided, extobj and axes contain borrowed references */
PyObject *extobj = NULL, *axes = NULL;
/* but type_tup has its own reference */
PyObject *type_tup = NULL;
int keepdims = -1;

if (ufunc == NULL) {
Expand Down Expand Up @@ -2772,8 +2781,10 @@ PyUFunc_GenericFunction(PyUFuncObject *ufunc,
NPY_ORDER order = NPY_KEEPORDER;
/* Use the default assignment casting rule */
NPY_CASTING casting = NPY_DEFAULT_ASSIGN_CASTING;
/* When provided, extobj and typetup contain borrowed references */
PyObject *extobj = NULL, *type_tup = NULL;
/* When provided, extobj contains a borrowed reference */
PyObject *extobj = NULL;
/* but type_tup has its own reference */
PyObject *type_tup = NULL;

if (ufunc == NULL) {
PyErr_SetString(PyExc_ValueError, "function not supported");
Expand Down
10 changes: 10 additions & 0 deletions numpy/core/tests/test_ufunc.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ def test_sig_dtype(self):
assert_raises(RuntimeError, np.add, 1, 2, signature='ii->i',
dtype=int)

def test_extobj_refcount(self):
# Should not segfault with USE_DEBUG.
assert_raises(TypeError, np.add, 1, 2, extobj=[4096], parrot=True)


class TestUfunc(object):
def test_pickle(self):
Expand Down Expand Up @@ -717,6 +721,10 @@ def test_axes_argument(self):
assert_raises(ValueError, mm, z, z, out=z[:, 0])
assert_raises(ValueError, mm, z[1], z, axes=[0, 1])
assert_raises(ValueError, mm, z, z, out=z[0], axes=[0, 1])
# Regular ufuncs should not accept axes.
assert_raises(TypeError, np.add, 1., 1., axes=[0])
# should be able to deal with bad unrelated kwargs.
assert_raises(TypeError, mm, z, z, axes=[0, 1], parrot=True)

def test_keepdims_argument(self):
# inner1d signature: '(i),(i)->()'
Expand Down Expand Up @@ -784,6 +792,8 @@ def test_keepdims_argument(self):
mm = umt.matrix_multiply
assert_raises(TypeError, mm, a, b, keepdims=True)
assert_raises(TypeError, mm, a, b, keepdims=False)
# Regular ufuncs should not accept keepdims.
assert_raises(TypeError, np.add, 1., 1., keepdims=False)

def test_innerwt(self):
a = np.arange(6).reshape((2, 3))
Expand Down
0