8000 BUG: Fix incorrect/missing reference cleanups found using valgrind by seberg · Pull Request #12624 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

BUG: Fix incorrect/missing reference cleanups found using valgrind #12624

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 16 commits into from
Jan 2, 2019
Merged
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 files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions numpy/core/src/multiarray/_multiarray_tests.c.src
Original file line number Diff line number Diff line change
Expand Up @@ -1871,11 +1871,14 @@ printf_float_g(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
static PyObject *
getset_numericops(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED(args))
{
PyObject * ops = PyArray_GetNumericOps();
PyObject *ret;
PyObject *ops = PyArray_GetNumericOps();
if (ops == NULL) {
return NULL;
}
return PyLong_FromLong(PyArray_SetNumericOps(ops));
ret = PyLong_FromLong(PyArray_SetNumericOps(ops));
Py_DECREF(ops);
return ret;
}

static PyMethodDef Multiarray_TestsMethods[] = {
Expand Down
4 changes: 4 additions & 0 deletions numpy/core/src/multiarray/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,10 @@ _buffer_info_new(PyObject *obj)
PyArray_Descr *descr = NULL;
int err = 0;

/*
* Note that the buffer info is cached as pyints making them appear like
* unreachable lost memory to valgrind.
*/
Copy link
Member Author

Choose a reason for hiding this comment

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

Frankly, right now I do not understand the logic of the cache, but I did not try to either and I guess they are very small objects.

info = malloc(sizeof(_buffer_info_t));
if (info == NULL) {
PyErr_NoMemory();
Expand Down
10 changes: 5 additions & 5 deletions numpy/core/src/multiarray/common.c
8000
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,

if (string_type == NPY_STRING) {
if ((temp = PyObject_Str(obj)) == NULL) {
return -1;
goto fail;
}
#if defined(NPY_PY3K)
#if PY_VERSION_HEX >= 0x03030000
Expand All @@ -182,7 +182,7 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
#else
if ((temp = PyObject_Unicode(obj)) == NULL) {
#endif
return -1;
goto fail;
}
itemsize = PyUnicode_GET_DATA_SIZE(temp);
#ifndef Py_UNICODE_WIDE
Expand Down Expand Up @@ -216,7 +216,7 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,

if (string_type == NPY_STRING) {
if ((temp = PyObject_Str(obj)) == NULL) {
return -1;
goto fail;
}
#if defined(NPY_PY3K)
#if PY_VERSION_HEX >= 0x03030000
Expand All @@ -234,7 +234,7 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
#else
if ((temp = PyObject_Unicode(obj)) == NULL) {
#endif
return -1;
goto fail;
}
itemsize = PyUnicode_GET_DATA_SIZE(temp);
#ifndef Py_UNICODE_WIDE
Expand Down Expand Up @@ -511,7 +511,7 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
PyArray_Descr *res_dtype = PyArray_PromoteTypes(dtype, *out_dtype);
Py_DECREF(dtype);
if (res_dtype == NULL) {
return -1;
goto fail;
}
if (!string_type &&
res_dtype->type_num == NPY_UNICODE &&
Expand Down
2 changes: 2 additions & 0 deletions numpy/core/src/multiarray/compiled_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1575,6 +1575,7 @@ pack_bits(PyObject *input, int axis)
if (!PyArray_ISBOOL(inp) && !PyArray_ISINTEGER(inp)) {
PyErr_SetString(PyExc_TypeError,
"Expected an input array of integer or boolean data type");
Py_DECREF(inp);
goto fail;
}

Expand Down Expand Up @@ -1682,6 +1683,7 @@ unpack_bits(PyObject *input, int axis)
if (PyArray_TYPE(inp) != NPY_UBYTE) {
PyErr_SetString(PyExc_TypeError,
"Expected an input array of unsigned byte data type");
Py_DECREF(inp);
goto fail;
}

Expand Down
15 changes: 8 additions & 7 deletions numpy/core/src/multiarray/ctors.c
Original file line number Diff line number Diff line change
Expand Up @@ -2128,12 +2128,15 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags)
*/

/* 2017-Nov-10 1.14 */
if (DEPRECATE("NPY_ARRAY_UPDATEIFCOPY, NPY_ARRAY_INOUT_ARRAY, and "
"NPY_ARRAY_INOUT_FARRAY are deprecated, use NPY_WRITEBACKIFCOPY, "
"NPY_ARRAY_INOUT_ARRAY2, or NPY_ARRAY_INOUT_FARRAY2 respectively "
"instead, and call PyArray_ResolveWritebackIfCopy before the "
"array is deallocated, i.e. before the last call to Py_DECREF.") < 0)
if (DEPRECATE(
"NPY_ARRAY_UPDATEIFCOPY, NPY_ARRAY_INOUT_ARRAY, and "
"NPY_ARRAY_INOUT_FARRAY are deprecated, use NPY_WRITEBACKIFCOPY, "
"NPY_ARRAY_INOUT_ARRAY2, or NPY_ARRAY_INOUT_FARRAY2 respectively "
"instead, and call PyArray_ResolveWritebackIfCopy before the "
"array is deallocated, i.e. before the last call to Py_DECREF.") < 0) {
Py_DECREF(ret);
return NULL;
}
Py_INCREF(arr);
if (PyArray_SetWritebackIfCopyBase(ret, arr) < 0) {
Py_DECREF(ret);
Expand All @@ -2160,14 +2163,12 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags)

Py_DECREF(newtype);
if (needview) {
PyArray_Descr *dtype = PyArray_DESCR(arr);
PyTypeObject *subtype = NULL;

if (flags & NPY_ARRAY_ENSUREARRAY) {
subtype = &PyArray_Type;
}

Py_INCREF(dtype);
ret = (PyArrayObject *)PyArray_View(arr, NULL, subtype);
if (ret == NULL) {
return NULL;
Expand Down
16 changes: 12 additions & 4 deletions numpy/core/src/multiarray/datetime.c
Original file line number Diff line number Diff line change
Expand Up @@ -3822,18 +3822,26 @@ recursive_find_object_timedelta64_type(PyObject *obj,
* single object using [()], but not by using
* __getitem__(integer) approaches
*/
PyObject *item, *meth, *args;
PyObject *item, *args;

meth = PyObject_GetAttrString(obj, "__getitem__");
args = Py_BuildValue("(())");
item = PyObject_CallObject(meth, args);
args = PyTuple_New(0);
if (args == NULL) {
return 0;
}
item = PyObject_GetItem(obj, args);
Py_DECREF(args);
if (item == NULL) {
return 0;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

The code above does not seem super pretty, but I am not quite sure that subclasses are not supposed to get a chance here, so PyObject_GetItem is no behaviour change I think. Oddly the datetime code looks a bit different than the timedelta one above.

/*
* NOTE: may need other type checks here in the future
* for expanded 0 D datetime array conversions?
*/
if (PyDelta_Check(item)) {
Py_DECREF(item);
return delta_checker(meta);
}
Py_DECREF(item);
}
}
}
Expand Down
9 changes: 8 additions & 1 deletion numpy/core/src/multiarray/descriptor.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ _convert_from_array_descr(PyObject *obj, int align)
#if defined(NPY_PY3K)
Py_DECREF(name);
#endif
Py_DECREF(conv);
goto fail;
}
dtypeflags |= (conv->flags & NPY_FROM_FIELDS);
Expand Down Expand Up @@ -837,9 +838,11 @@ _use_inherit(PyArray_Descr *type, PyObject *newobj, int *errflag)
else if (new->elsize != conv->elsize) {
PyErr_SetString(PyExc_ValueError,
"mismatch in size of old and new data-descriptor");
Py_DECREF(new);
goto fail;
}
else if (invalid_union_object_dtype(new, conv)) {
Py_DECREF(new);
goto fail;
}

Expand Down Expand Up @@ -1728,6 +1731,7 @@ PyArray_DescrNew(PyArray_Descr *base)
newdescr->c_metadata = NPY_AUXDATA_CLONE(base->c_metadata);
if (newdescr->c_metadata == NULL) {
PyErr_NoMemory();
/* TODO: This seems wrong, as the old fields get decref'd? */
Py_DECREF(newdescr);
return NULL;
}
Expand Down Expand Up @@ -3336,12 +3340,15 @@ static PyObject *
_subscript_by_index(PyArray_Descr *self, Py_ssize_t i)
{
PyObject *name = PySequence_GetItem(self->names, i);
PyObject *ret;
if (name == NULL) {
PyErr_Format(PyExc_IndexError,
"Field index %zd out of range.", i);
return NULL;
}
return _subscript_by_name(self, name);
ret = _subscript_by_name(self, name);
Py_DECREF(name);
return ret;
}

static PyObject *
Expand Down
2 changes: 2 additions & 0 deletions numpy/core/src/multiarray/methods.c
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,7 @@ array_argsort(PyArrayObject *self, PyObject *args, PyObject *kwds)
return NULL;
}
newd = PyArray_DescrNew(saved);
Py_DECREF(newd->names);
newd->names = new_name;
((PyArrayObject_fields *)self)->descr = newd;
}
Expand Down Expand Up @@ -1435,6 +1436,7 @@ array_argpartition(PyArrayObject *self, PyObject *args, PyObject *kwds)
return NULL;
}
newd = PyArray_DescrNew(saved);
Py_DECREF(newd->names);
newd->names = new_name;
((PyArrayObject_fields *)self)->descr = newd;
}
Expand Down
8 changes: 7 additions & 1 deletion numpy/core/src/multiarray/multiarraymodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3255,6 +3255,7 @@ array_datetime_data(PyObject *NPY_UNUSED(dummy), PyObject *args)
}

meta = get_datetime_metadata_from_dtype(dtype);
Py_DECREF(dtype);
Copy link
Member Author

Choose a reason for hiding this comment

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

This is probably one of the few ones that could hurt in practice, if someone prints a lot of datetime objects for some reason.

if (meta == NULL) {
return NULL;
}
Expand Down Expand Up @@ -3619,13 +3620,15 @@ _vec_string_with_args(PyArrayObject* char_array, PyArray_Descr* type,
if (nargs == -1 || nargs > NPY_MAXARGS) {
PyErr_Format(PyExc_ValueError,
"len(args) must be < %d", NPY_MAXARGS - 1);
Py_DECREF(type);
goto err;
}

broadcast_args[0] = (PyObject*)char_array;
for (i = 1; i < nargs; i++) {
PyObject* item = PySequence_GetItem(args, i-1);
if (item == NULL) {
Py_DECREF(type);
goto err;
}
broadcast_args[i] = item;
Expand All @@ -3634,6 +3637,7 @@ _vec_string_with_args(PyArrayObject* char_array, PyArray_Descr* type,
in_iter = (PyArrayMultiIterObject*)PyArray_MultiIterFromObjects
(broadcast_args, nargs, 0);
if (in_iter == NULL) {
Py_DECREF(type);
goto err;
}
n = in_iter->numiter;
Expand Down Expand Up @@ -3714,6 +3718,7 @@ _vec_string_no_args(PyArrayObject* char_array,

in_iter = (PyArrayIterObject*)PyArray_IterNew((PyObject*)char_array);
if (in_iter == NULL) {
Py_DECREF(type);
goto err;
}

Expand Down Expand Up @@ -3770,7 +3775,7 @@ static PyObject *
_vec_string(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
{
PyArrayObject* char_array = NULL;
PyArray_Descr *type = NULL;
PyArray_Descr *type;
PyObject* method_name;
PyObject* args_seq = NULL;

Expand Down Expand Up @@ -3807,6 +3812,7 @@ _vec_string(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
result = _vec_string_with_args(char_array, type, method, args_seq);
}
else {
Py_DECREF(type);
PyErr_SetString(PyExc_TypeError,
"'args' must be a sequence of arguments");
goto err;
Expand Down
7 changes: 4 additions & 3 deletions numpy/core/src/multiarray/nditer_constr.c
10000
Original file line number Diff line number Diff line change
Expand Up @@ -1248,9 +1248,9 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in,
return 1;

fail_nop:
iop = nop;
iop = nop - 1;
fail_iop:
for (i = 0; i < iop; ++i) {
for (i = 0; i < iop+1; ++i) {
Py_XDECREF(op[i]);
Py_XDECREF(op_dtype[i]);
}
Expand Down Expand Up @@ -3157,6 +3157,7 @@ npyiter_allocate_transfer_functions(NpyIter *iter)
&stransfer,
&transferdata,
&needs_api) != NPY_SUCCEED) {
iop -= 1; /* This one cannot be cleaned up yet. */
goto fail;
}
readtransferfn[iop] = stransfer;
Expand Down Expand Up @@ -3250,7 +3251,7 @@ npyiter_allocate_transfer_functions(NpyIter *iter)
return 1;

fail:
for (i = 0; i < iop; ++i) {
for (i = 0; i < iop+1; ++i) {
if (readtransferdata[iop] != NULL) {
NPY_AUXDATA_FREE(readtransferdata[iop]);
readtransferdata[iop] = NULL;
Expand Down
2 changes: 2 additions & 0 deletions numpy/core/src/multiarray/nditer_pywrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2355,6 +2355,8 @@ npyiter_close(NewNpyArrayIterObject *self)
}
ret = NpyIter_Deallocate(iter);
self->iter = NULL;
Py_XDECREF(self->nested_child);
self->nested_child = NULL;
if (ret < 0) {
return NULL;
}
Expand Down
7 changes: 4 additions & 3 deletions numpy/core/src/multiarray/number.c
Original file line number Diff line number Diff line change
Expand Up @@ -599,15 +599,16 @@ array_positive(PyArrayObject *m1)
PyErr_Restore(exc, val, tb);
return NULL;
}
Py_XDECREF(exc);
Py_XDECREF(val);
Py_XDECREF(tb);

/* 2018-06-28, 1.16.0 */
if (DEPRECATE("Applying '+' to a non-numerical array is "
"ill-defined. Returning a copy, but in the future "
"this will error.") < 0) {
return NULL;
}
Py_XDECREF(exc);
Py_XDECREF(val);
Py_XDECREF(tb);
value = PyArray_Return((PyArrayObject *)PyArray_Copy(m1));
}
return value;
Expand Down
1 change: 1 addition & 0 deletions numpy/core/src/umath/_struct_ufunc_tests.c.src
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ PyMODINIT_FUNC init_struct_ufunc_tests(void)
dtypes,
NULL);

Py_DECREF(dtype);
d = PyModule_GetDict(m);

PyDict_SetItemString(d, "add_triplet", add_triplet);
Expand Down
2 changes: 1 addition & 1 deletion numpy/core/src/umath/_umath_tests.c.src
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ UMath_Tests_test_signature(PyObject *NPY_UNUSED(dummy), PyObject *args)
core_dim_sizes = Py_None;
}
Py_DECREF(f);
return Py_BuildValue("iOOOO", core_enabled, core_num_dims,
return Py_BuildValue("iNNNN", core_enabled, core_num_dims,
core_dim_ixs, core_dim_flags, core_dim_sizes);

fail:
Expand Down
1 change: 0 additions & 1 deletion numpy/core/src/umath/reduction.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ conform_reduce_result(int ndim, npy_bool *axis_flags,
return NULL;
}

Py_INCREF(ret);
if (PyArray_SetWritebackIfCopyBase(ret_copy, (PyArrayObject *)ret) < 0) {
Py_DECREF(ret);
Py_DECREF(ret_copy);
Expand Down
2 changes: 2 additions & 0 deletions numpy/core/src/umath/ufunc_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -3063,6 +3063,8 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
Py_XDECREF(axis);
Py_XDECREF(full_args.in);
Py_XDECREF(full_args.out);
PyArray_free(remap_axis_memory);
PyArray_free(remap_axis);

NPY_UF_DBG_PRINT1("Returning code %d\n", reval);

Expand Down
Loading
0