Skip to content

Commit a3e8c12

Browse files
committed
Merge pull request numpy#3965 from seberg/valgrind
MAINT: Initialize strides in NpyIter and silence valgrind
2 parents 8988715 + 3a01f4e commit a3e8c12

File tree

10 files changed

+61
-35
lines changed

10 files changed

+61
-35
lines changed

numpy/core/src/multiarray/convert_datatype.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1396,7 +1396,7 @@ static int min_scalar_type_num(char *valueptr, int type_num,
13961396
break;
13971397
}
13981398
case NPY_CLONGDOUBLE: {
1399-
npy_cdouble value = *(npy_cdouble *)valueptr;
1399+
npy_clongdouble value = *(npy_clongdouble *)valueptr;
14001400
/*
14011401
if (value.imag == 0) {
14021402
return min_scalar_type_num((char *)&value.real,

numpy/core/src/multiarray/multiarraymodule.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,6 +1548,7 @@ _prepend_ones(PyArrayObject *arr, int nd, int ndmin, NPY_ORDER order)
15481548
PyArray_FLAGS(arr),
15491549
(PyObject *)arr);
15501550
if (ret == NULL) {
1551+
Py_DECREF(arr);
15511552
return NULL;
15521553
}
15531554
/* steals a reference to arr --- so don't increment here */

numpy/core/src/multiarray/nditer_constr.c

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,11 +1161,7 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in,
11611161

11621162
/* Check the readonly/writeonly flags, and fill in op_itflags */
11631163
if (!npyiter_check_per_op_flags(op_flags[iop], &op_itflags[iop])) {
1164-
for (i = 0; i <= iop; ++i) {
1165-
Py_XDECREF(op[i]);
1166-
Py_XDECREF(op_dtype[i]);
1167-
}
1168-
return 0;
1164+
goto fail_iop;
11691165
}
11701166

11711167
/* Extract the operand which is for masked iteration */
@@ -1174,11 +1170,7 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in,
11741170
PyErr_SetString(PyExc_ValueError,
11751171
"Only one iterator operand may receive an "
11761172
"ARRAYMASK flag");
1177-
for (i = 0; i <= iop; ++i) {
1178-
Py_XDECREF(op[i]);
1179-
Py_XDECREF(op_dtype[i]);
1180-
}
1181-
return 0;
1173+
goto fail_iop;
11821174
}
11831175

11841176
maskop = iop;
@@ -1199,11 +1191,7 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in,
11991191
&op_dtype[iop],
12001192
flags,
12011193
op_flags[iop], &op_itflags[iop])) {
1202-
for (i = 0; i <= iop; ++i) {
1203-
Py_XDECREF(op[i]);
1204-
Py_XDECREF(op_dtype[i]);
1205-
}
1206-
return 0;
1194+
goto fail_iop;
12071195
}
12081196
}
12091197

@@ -1217,13 +1205,9 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in,
12171205
}
12181206
}
12191207
if (all_null) {
1220-
for (i = 0; i < nop; ++i) {
1221-
Py_XDECREF(op[i]);
1222-
Py_XDECREF(op_dtype[i]);
1223-
}
12241208
PyErr_SetString(PyExc_ValueError,
12251209
"At least one iterator operand must be non-NULL");
1226-
return 0;
1210+
goto fail_nop;
12271211
}
12281212
}
12291213

@@ -1232,17 +1216,26 @@ npyiter_prepare_operands(int nop, PyArrayObject **op_in,
12321216
"An iterator operand was flagged as WRITEMASKED, "
12331217
"but no ARRAYMASK operand was given to supply "
12341218
"the mask");
1235-
return 0;
1219+
goto fail_nop;
12361220
}
12371221
else if (!any_writemasked_ops && maskop >= 0) {
12381222
PyErr_SetString(PyExc_ValueError,
12391223
"An iterator operand was flagged as the ARRAYMASK, "
12401224
"but no WRITEMASKED operands were given to use "
12411225
"the mask");
1242-
return 0;
1226+
goto fail_nop;
12431227
}
12441228

12451229
return 1;
1230+
1231+
fail_nop:
1232+
iop = nop;
1233+
fail_iop:
1234+
for (i = 0; i < iop; ++i) {
1235+
Py_XDECREF(op[i]);
1236+
Py_XDECREF(op_dtype[i]);
1237+
}
1238+
return 0;
12461239
}
12471240

12481241
static const char *
@@ -1565,6 +1558,7 @@ npyiter_fill_axisdata(NpyIter *iter, npy_uint32 flags, npyiter_opitflags *op_itf
15651558
NAD_SHAPE(axisdata) = 1;
15661559
NAD_INDEX(axisdata) = 0;
15671560
memcpy(NAD_PTRS(axisdata), op_dataptr, NPY_SIZEOF_INTP*nop);
1561+
memset(NAD_STRIDES(axisdata), 0, NPY_SIZEOF_INTP*nop);
15681562
}
15691563

15701564
/* Now process the operands, filling in the axisdata */

numpy/core/src/multiarray/number.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,7 @@ array_int(PyArrayObject *v)
771771
PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) {
772772
PyErr_SetString(PyExc_TypeError,
773773
"object array may be self-referencing");
774+
Py_DECREF(pv);
774775
return NULL;
775776
}
776777

@@ -812,6 +813,7 @@ array_float(PyArrayObject *v)
812813
PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) {
813814
PyErr_SetString(PyExc_TypeError,
814815
"object array may be self-referencing");
816+
Py_DECREF(pv);
815817
return NULL;
816818
}
817819
pv2 = Py_TYPE(pv)->tp_as_number->nb_float(pv);
@@ -831,14 +833,19 @@ array_long(PyArrayObject *v)
831833
return NULL;
832834
}
833835
pv = PyArray_DESCR(v)->f->getitem(PyArray_DATA(v), v);
836+
if (pv == NULL) {
837+
return NULL;
838+
}
834839
if (Py_TYPE(pv)->tp_as_number == 0) {
835840
PyErr_SetString(PyExc_TypeError, "cannot convert to an int; "\
836841
"scalar object is not a number");
842+
Py_DECREF(pv);
837843
return NULL;
838844
}
839845
if (Py_TYPE(pv)->tp_as_number->nb_long == 0) {
840846
PyErr_SetString(PyExc_TypeError, "don't know how to convert "\
841847
"scalar number to long");
848+
Py_DECREF(pv);
842849
return NULL;
843850
}
844851
/*
@@ -849,6 +856,7 @@ array_long(PyArrayObject *v)
849856
PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) {
850857
PyErr_SetString(PyExc_TypeError,
851858
"object array may be self-referencing");
859+
Py_DECREF(pv);
852860
return NULL;
853861
}
854862
pv2 = Py_TYPE(pv)->tp_as_number->nb_long(pv);
@@ -866,14 +874,19 @@ array_oct(PyArrayObject *v)
866874
return NULL;
867875
}
868876
pv = PyArray_DESCR(v)->f->getitem(PyArray_DATA(v), v);
877+
if (pv == NULL) {
878+
return NULL;
879+
}
869880
if (Py_TYPE(pv)->tp_as_number == 0) {
870881
PyErr_SetString(PyExc_TypeError, "cannot convert to an int; "\
871882
"scalar object is not a number");
883+
Py_DECREF(pv);
872884
return NULL;
873885
}
874886
if (Py_TYPE(pv)->tp_as_number->nb_oct == 0) {
875887
PyErr_SetString(PyExc_TypeError, "don't know how to convert "\
876888
"scalar number to oct");
889+
Py_DECREF(pv);
877890
return NULL;
878891
}
879892
/*
@@ -884,6 +897,7 @@ array_oct(PyArrayObject *v)
884897
PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) {
885898
PyErr_SetString(PyExc_TypeError,
886899
"object array may be self-referencing");
900+
Py_DECREF(pv);
887901
return NULL;
888902
}
889903
pv2 = Py_TYPE(pv)->tp_as_number->nb_oct(pv);
@@ -901,14 +915,19 @@ array_hex(PyArrayObject *v)
901915
return NULL;
902916
}
903917
pv = PyArray_DESCR(v)->f->getitem(PyArray_DATA(v), v);
918+
if (pv == NULL) {
919+
return NULL;
920+
}
904921
if (Py_TYPE(pv)->tp_as_number == 0) {
905922
PyErr_SetString(PyExc_TypeError, "cannot convert to an int; "\
906923
"scalar object is not a number");
924+
Py_DECREF(pv);
907925
return NULL;
908926
}
909927
if (Py_TYPE(pv)->tp_as_number->nb_hex == 0) {
910928
PyErr_SetString(PyExc_TypeError, "don't know how to convert "\
911929
"scalar number to hex");
930+
Py_DECREF(pv);
912931
return NULL;
913932
}
914933
/*
@@ -919,6 +938,7 @@ array_hex(PyArrayObject *v)
919938
PyDataType_REFCHK(PyArray_DESCR((PyArrayObject *)pv))) {
920939
PyErr_SetString(PyExc_TypeError,
921940
"object array may be self-referencing");
941+
Py_DECREF(pv);
922942
return NULL;
923943
}
924944
pv2 = Py_TYPE(pv)->tp_as_number->nb_hex(pv);

numpy/core/src/umath/test_rational.c.src

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1242,12 +1242,15 @@ PyMODINIT_FUNC inittest_rational(void) {
12421242
PyErr_Format(PyExc_AssertionError, \
12431243
"ufunc %s takes %d arguments, our loop takes %ld", \
12441244
#name, ufunc->nargs, sizeof(_types)/sizeof(int)); \
1245+
Py_DECREF(ufunc); \
12451246
goto fail; \
12461247
} \
12471248
if (PyUFunc_RegisterLoopForType((PyUFuncObject*)ufunc, npy_rational, \
12481249
rational_ufunc_##name, _types, 0) < 0) { \
1250+
Py_DECREF(ufunc); \
12491251
goto fail; \
12501252
} \
1253+
Py_DECREF(ufunc); \
12511254
}
12521255
#define REGISTER_UFUNC_BINARY_RATIONAL(name) \
12531256
REGISTER_UFUNC(name, {npy_rational, npy_rational, npy_rational})

numpy/core/src/umath/ufunc_object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5083,7 +5083,7 @@ ufunc_at(PyUFuncObject *ufunc, PyObject *args)
50835083
}
50845084
else {
50855085
Py_INCREF(PyArray_DESCR(op1_array));
5086-
array_operands[2] = new_array_op(op1_array, iter->dataptr);
5086+
array_operands[1] = new_array_op(op1_array, iter->dataptr);
50875087
array_operands[2] = NULL;
50885088
}
50895089

numpy/core/tests/test_api.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,13 @@ def test_array_array():
122122

123123
# Try with lists...
124124
assert_equal(np.array([None] * 10, dtype=np.float64),
125-
np.empty((10,), dtype=np.float64) + np.nan)
125+
np.full((10,), np.nan, dtype=np.float64))
126126
assert_equal(np.array([[None]] * 10, dtype=np.float64),
127-
np.empty((10, 1), dtype=np.float64) + np.nan)
127+
np.full((10, 1), np.nan, dtype=np.float64))
128128
assert_equal(np.array([[None] * 10], dtype=np.float64),
129-
np.empty((1, 10), dtype=np.float64) + np.nan)
129+
np.full((1, 10), np.nan, dtype=np.float64))
130130
assert_equal(np.array([[None] * 10] * 10, dtype=np.float64),
131-
np.empty((10, 10), dtype=np.float64) + np.nan)
131+
np.full((10, 10), np.nan, dtype=np.float64))
132132

133133
assert_equal(np.array([1.0] * 10, dtype=np.float64),
134134
np.ones((10,), dtype=np.float64))
@@ -141,13 +141,13 @@ def test_array_array():
141141

142142
# Try with tuples
143143
assert_equal(np.array((None,) * 10, dtype=np.float64),
144-
np.empty((10,), dtype=np.float64) + np.nan)
144+
np.full((10,), np.nan, dtype=np.float64))
145145
assert_equal(np.array([(None,)] * 10, dtype=np.float64),
146-
np.empty((10, 1), dtype=np.float64) + np.nan)
146+
np.full((10, 1), np.nan, dtype=np.float64))
147147
assert_equal(np.array([(None,) * 10], dtype=np.float64),
148-
np.empty((1, 10), dtype=np.float64) + np.nan)
148+
np.full((1, 10), np.nan, dtype=np.float64))
149149
assert_equal(np.array([(None,) * 10] * 10, dtype=np.float64),
150-
np.empty((10, 10), dtype=np.float64) + np.nan)
150+
np.full((10, 10), np.nan, dtype=np.float64))
151151

152152
assert_equal(np.array((1.0,) * 10, dtype=np.float64),
153153
np.ones((10,), dtype=np.float64))

numpy/core/tests/test_multiarray.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1624,7 +1624,7 @@ def __rop__(self, *other):
16241624

16251625
# Check behavior against both bare ndarray objects and a
16261626
# ndarray subclasses with and without their own override
1627-
obj = cls((1,))
1627+
obj = cls((1,), buffer=np.ones(1,))
16281628

16291629
arr_objs = [np.array([1]),
16301630
np.array([2]).view(OtherNdarraySubclass),

numpy/core/tests/test_regression.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1654,14 +1654,22 @@ def test_object_array_self_reference(self):
16541654
assert_raises(TypeError, oct, a)
16551655
assert_raises(TypeError, hex, a)
16561656

1657+
# Test the same for a circular reference.
1658+
b = np.array(a, dtype=object)
1659+
a[()] = b
1660+
assert_raises(TypeError, int, a)
1661+
# Numpy has no tp_traverse currently, so circular references
1662+
# cannot be detected. So resolve it:
1663+
a[()] = 0
1664+
16571665
# This was causing a to become like the above
16581666
a = np.array(0, dtype=object)
16591667
a[...] += 1
16601668
assert_equal(a, 1)
16611669

16621670
def test_object_array_self_copy(self):
16631671
# An object array being copied into itself DECREF'ed before INCREF'ing
1664-
# causing segmentation faults (gh-3787)
1672+
# causing segmentation faults (gh-3787)
16651673
a = np.array(object(), dtype=object)
16661674
np.copyto(a, a)
16671675
assert_equal(sys.getrefcount(a[()]), 2)

numpy/linalg/tests/test_linalg.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,7 +616,7 @@ def do(self, a, b):
616616
expect_resids.shape = (1,)
617617
assert_equal(residuals.shape, expect_resids.shape)
618618
else:
619-
expect_resids = type(x)([])
619+
expect_resids = np.array([]).view(type(x))
620620
assert_almost_equal(residuals, expect_resids)
621621
assert_(np.issubdtype(residuals.dtype, np.floating))
622622
assert_(imply(isinstance(b, matrix), isinstance(x, matrix)))

0 commit comments

Comments
 (0)