8000 Merge branch 'fix-attribute-delete' · numpy-buildbot/numpy@b20a013 · GitHub
[go: up one dir, main page]

Skip to content

Commit b20a013

Browse files
committed
Merge branch 'fix-attribute-delete'
* fix-attribute-delete: TST: Test attempted deletion of attributes/iterator_elements. BUG: Make attempted attribute/iterator_element deletions not segfault.
2 parents ae3dd33 + 4ba819a commit b20a013

File tree

10 files changed

+185
-38
lines changed

10 files changed

+185
-38
lines changed

numpy/core/src/multiarray/descriptor.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1807,6 +1807,11 @@ arraydescr_names_set(PyArray_Descr *self, PyObject *val)
18071807
PyObject *new_names;
18081808
PyObject *new_fields;
18091809

1810+
if (val == NULL) {
1811+
PyErr_SetString(PyExc_AttributeError,
1812+
"Cannot delete dtype names attribute");
1813+
return -1;
1814+
}
18101815
if (!PyDataType_HASFIELDS(self)) {
18111816
PyErr_SetString(PyExc_ValueError,
18121817
"there are no fields defined");

numpy/core/src/multiarray/flagsobject.c

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,14 @@ arrayflags_maskna_get(PyArrayFlagsObject *self)
276276
static int
277277
arrayflags_maskna_set(PyArrayFlagsObject *self, PyObject *obj)
278278
{
279+
if (obj == NULL) {
280+
PyErr_SetString(PyExc_AttributeError,
281+
"Cannot delete flags maskna attribute");
282+
return -1;
283+
}
279284
if (self->arr == NULL) {
280-
PyErr_SetString(PyExc_ValueError, "Cannot set flags on array scalars.");
285+
PyErr_SetString(PyExc_ValueError,
286+
"Cannot set flags on array scalars.");
281287
return -1;
282288
}
283289

@@ -287,7 +293,7 @@ arrayflags_maskna_set(PyArrayFlagsObject *self, PyObject *obj)
287293
else {
288294
if (self->flags & NPY_ARRAY_MASKNA) {
289295
PyErr_SetString(PyExc_ValueError,
290-
"Cannot remove a NumPy array's NA mask");
296+
"Cannot remove a NumPy array's NA mask");
291297
return -1;
292298
}
293299
else {
@@ -313,8 +319,14 @@ arrayflags_ownmaskna_get(PyArrayFlagsObject *self)
313319
static int
314320
arrayflags_ownmaskna_set(PyArrayFlagsObject *self, PyObject *obj)
315321
{
322+
if (obj == NULL) {
323+
PyErr_SetString(PyExc_AttributeError,
324+
"Cannot delete flags ownmaskna attributes");
325+
return -1;
326+
}
316327
if (self->arr == NULL) {
317-
PyErr_SetString(PyExc_ValueError, "Cannot set flags on array scalars.");
328+
PyErr_SetString(PyExc_ValueError,
329+
"Cannot set flags on array scalars.");
318330
return -1;
319331
}
320332

@@ -338,8 +350,15 @@ static int
338350
arrayflags_updateifcopy_set(PyArrayFlagsObject *self, PyObject *obj)
339351
{
340352
PyObject *res;
353+
354+
if (obj == NULL) {
355+
PyErr_SetString(PyExc_AttributeError,
356+
"Cannot delete flags updateifcopy attribute");
357+
return -1;
358+
}
341359
if (self->arr == NULL) {
342-
PyErr_SetString(PyExc_ValueError, "Cannot set flags on array scalars.");
360+
PyErr_SetString(PyExc_ValueError,
361+
"Cannot set flags on array scalars.");
343362
return -1;
344363
}
345364
res = PyObject_CallMethod(self->arr, "setflags", "OOO", Py_None, Py_None,
@@ -355,8 +374,15 @@ static int
355374
arrayflags_aligned_set(PyArrayFlagsObject *self, PyObject *obj)
356375
{
357376
PyObject *res;
377+
378+
if (obj == NULL) {
379+
PyErr_SetString(PyExc_AttributeError,
380+
"Cannot delete flags aligned attribute");
381+
return -1;
382+
}
358383
if (self->arr == NULL) {
359-
PyErr_SetString(PyExc_ValueError, "Cannot set flags on array scalars.");
384+
PyErr_SetString(PyExc_ValueError,
385+
"Cannot set flags on array scalars.");
360386
return -1;
361387
}
362388
res = PyObject_CallMethod(self->arr, "setflags", "OOO", Py_None,
@@ -373,8 +399,15 @@ static int
373399
arrayflags_writeable_set(PyArrayFlagsObject *self, PyObject *obj)
374400
{
375401
PyObject *res;
402+
403+
if (obj == NULL) {
404+
PyErr_SetString(PyExc_AttributeError,
405+
"Cannot delete flags writeable attribute");
406+
return -1;
407+
}
376408
if (self->arr == NULL) {
377-
PyErr_SetString(PyExc_ValueError, "Cannot set flags on array scalars.");
409+
PyErr_SetString(PyExc_ValueError,
410+
"Cannot set flags on array scalars.");
378411
return -1;
379412
}
380413
res = PyObject_CallMethod(self->arr, "setflags", "OOO",

numpy/core/src/multiarray/getset.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,7 @@ NPY_NO_EXPORT PyGetSetDef array_getsetlist[] = {
941941
(getter)array_ctypes_get,
942942
NULL,
943943
NULL, NULL},
944-
{ "T",
944+
{"T",
945945
(getter)array_transpose_get,
946946
NULL,
947947
NULL, NULL},

numpy/core/src/multiarray/iterators.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,12 @@ iter_ass_subscript(PyArrayIterObject *self, PyObject *ind, PyObject *val)
10371037
PyArray_CopySwapFunc *copyswap;
10381038

10391039

1040+
if (val == NULL) {
1041+
PyErr_SetString(PyExc_TypeError,
1042+
"Cannot delete iterator elements");
1043+
return -1;
1044+
}
1045+
10401046
if (ind == Py_Ellipsis) {
10411047
ind = PySlice_New(NULL, NULL, NULL);
10421048
retval = iter_ass_subscript(self, ind, val);

numpy/core/src/multiarray/na_object.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,14 +184,20 @@ na_payload_set(NpyNA_fields *self, PyObject *value)
184184
{
185185
long payload;
186186

187+
if (value == NULL) {
188+
PyErr_SetString(PyExc_AttributeError,
189+
"Cannot delete NA payload attribute");
190+
return -1;
191+
}
192+
187193
/* Don't allow changing the static singleton instance */
188194
if (self->is_singleton) {
189195
PyErr_SetString(PyExc_RuntimeError,
190196
"cannot change the payload of the NumPy NA singleton, "
191197
"make a new copy like 'numpy.NA(payload)'");
192198
return -1;
193199
}
194-
else if (value == NULL || value == Py_None) {
200+
else if (value == Py_None) {
195201
self->payload = NPY_NA_NOPAYLOAD;
196202
}
197203
else {
@@ -241,6 +247,11 @@ na_dtype_set(NpyNA_fields *self, PyObject *value)
241247
{
242248
PyArray_Descr *dtype = NULL;
243249

250+
if (value == NULL) {
251+
PyErr_SetString(PyExc_AttributeError,
252+
"Cannot delete NA dtype attribute");
253+
return -1;
254+
}
244255
/* Don't allow changing the static singleton instance */
245256
if (self->is_singleton) {
246257
PyErr_SetString(PyExc_RuntimeError,

numpy/core/src/multiarray/nditer_pywrap.c

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,15 +1612,14 @@ npyiter_multi_index_set(NewNpyArrayIterObject *self, PyObject *value)
16121612
{
16131613
npy_intp idim, ndim, multi_index[NPY_MAXDIMS];
16141614

1615-
if (self->iter == NULL) {
1616-
PyErr_SetString(PyExc_ValueError,
1617-
"Iterator is invalid");
1615+
if (value == NULL) {
1616+
PyErr_SetString(PyExc_AttributeError,
1617+
"Cannot delete nditer multi_index");
16181618
return -1;
16191619
}
1620-
1621-
if (value == NULL) {
1620+
if (self->iter == NULL) {
16221621
PyErr_SetString(PyExc_ValueError,
1623-
"Cannot delete the multi_index");
1622+
"Iterator is invalid");
16241623
return -1;
16251624
}
16261625

@@ -1684,15 +1683,14 @@ static PyObject *npyiter_index_get(NewNpyArrayIterObject *self)
16841683

16851684
static int npyiter_index_set(NewNpyArrayIterObject *self, PyObject *value)
16861685
{
1687-
if (self->iter == NULL) {
1688-
PyErr_SetString(PyExc_ValueError,
1689-
"Iterator is invalid");
1686+
if (value == NULL) {
1687+
PyErr_SetString(PyExc_AttributeError,
1688+
"Cannot delete nditer index");
16901689
return -1;
16911690
}
1692-
1693-
if (value == NULL) {
1691+
if (self->iter == NULL) {
16941692
PyErr_SetString(PyExc_ValueError,
1695-
"Cannot delete index");
1693+
"Iterator is invalid");
16961694
return -1;
16971695
}
16981696

@@ -1737,15 +1735,14 @@ static int npyiter_iterindex_set(NewNpyArrayIterObject *self, PyObject *value)
17371735
{
17381736
npy_intp iterindex;
17391737

1740-
if (self->iter == NULL) {
1741-
PyErr_SetString(PyExc_ValueError,
1742-
"Iterator is invalid");
1738+
if (value == NULL) {
1739+
PyErr_SetString(PyExc_AttributeError,
1740+
"Cannot delete nditer iterindex");
17431741
return -1;
17441742
}
1745-
1746-
if (value == NULL) {
1743+
if (self->iter == NULL) {
17471744
PyErr_SetString(PyExc_ValueError,
1748-
"Cannot delete iterindex");
1745+
"Iterator is invalid");
17491746
return -1;
17501747
}
17511748

@@ -1799,15 +1796,14 @@ static int npyiter_iterrange_set(NewNpyArrayIterObject *self, PyObject *value)
17991796
long istart = 0, iend = 0;
18001797
#endif
18011798

1802-
if (self->iter == NULL) {
1803-
PyErr_SetString(PyExc_ValueError,
1804-
"Iterator is invalid");
1799+
if (value == NULL) {
1800+
PyErr_SetString(PyExc_AttributeError,
1801+
"Cannot delete nditer iterrange");
18051802
return -1;
18061803
}
1807-
1808-
if (value == NULL) {
1804+
if (self->iter == NULL) {
18091805
PyErr_SetString(PyExc_ValueError,
1810-
"Cannot delete iterrange");
1806+
"Iterator is invalid");
18111807
return -1;
18121808
}
18131809

@@ -2173,8 +2169,8 @@ npyiter_seq_ass_item(NewNpyArrayIterObject *self, Py_ssize_t i, PyObject *v)
21732169

21742170

21752171
if (v == NULL) {
2176-
PyErr_SetString(PyExc_ValueError,
2177-
"can't delete iterator operands");
2172+
PyErr_SetString(PyExc_TypeError,
2173+
"Cannot delete iterator elements");
21782174
return -1;
21792175
}
21802176

@@ -2271,8 +2267,8 @@ npyiter_seq_ass_slice(NewNpyArrayIterObject *self, Py_ssize_t ilow,
22712267
Py_ssize_t i;
22722268

22732269
if (v == NULL) {
2274-
PyErr_SetString(PyExc_ValueError,
2275-
"cannot delete iterator elements");
2270+
PyErr_SetString(PyExc_TypeError,
2271+
"Cannot delete iterator elements");
22762272
return -1;
22772273
}
22782274

@@ -2376,6 +2372,11 @@ static int
23762372
npyiter_ass_subscript(NewNpyArrayIterObject *self, PyObject *op,
23772373
PyObject *value)
23782374
{
2375+
if (value == NULL) {
2376+
PyErr_SetString(PyExc_TypeError,
2377+
"Cannot delete iterator elements");
2378+
return -1;
2379+
}
23792380
if (self->iter == NULL || self->finished) {
23802381
PyErr_SetString(PyExc_ValueError,
23812382
"Iterator is past the end");

numpy/core/tests/test_dtype.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,5 +401,23 @@ def test_complex_dtype_repr(self):
401401
"dtype([('a', '<M8[D]'), ('b', '<m8[us]')])")
402402

403403

404+
class TestDtypeAttributeDeletion(object):
405+
406+
def test_dtype_non_writable_attributes_deletion(self):
407+
dt = np.dtype(np.double)
408+
attr = ["subdtype", "descr", "str", "name", "base", "shape",
409+
"isbuiltin", "isnative", "isalignedstruct", "fields",
410+
"metadata", "hasobject"]
411+
for s in attr:
412+
assert_raises(AttributeError, delattr, dt, s)
413+
414+
415+
def test_dtype_writable_attributes_deletion(self):
416+
dt = np.dtype(np.double)
417+
attr = ["names"]
418+
for s in attr:
419+
assert_raises(AttributeError, delattr, dt, s)
420+
421+
404422
if __name__ == "__main__":
405423
run_module_suite()

numpy/core/tests/test_multiarray.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2309,14 +2309,51 @@ def test_padded_struct_array(self):
23092309

23102310

23112311
class TestArrayAttributeDeletion(object):
2312-
"""ticket #2046, should not seqfault, raise AttributeError"""
23132312

2314-
def test_attribute_deletion(self):
2313+
def test_multiarray_writable_attributes_deletion(self):
2314+
"""ticket #2046, should not seqfault, raise AttributeError"""
23152315
a = np.ones(2)
23162316
attr = ['shape', 'strides', 'data', 'dtype', 'real', 'imag', 'flat']
23172317
for s in attr:
23182318
assert_raises(AttributeError, delattr, a, s)
23192319

23202320

2321+
def test_multiarray_not_writable_attributes_deletion(self):
2322+
a = np.ones(2)
2323+
attr = ["ndim", "flags", "itemsize", "size", "nbytes", "base",
2324+
"ctypes", "T", "__array_interface__", "__array_struct__",
2325+
"__array_priority__", "__array_finalize__"]
2326+
for s in attr:
2327+
assert_raises(AttributeError, delattr, a, s)
2328+
2329+
2330+
def test_multiarray_flags_writable_attribute_deletion(self):
2331+
a = np.ones(2).flags
2332+
attr = ['updateifcopy', 'aligned', 'writeable', 'maskna',
2333+
'ownmaskna']
2334+
for s in attr:
2335+
assert_raises(AttributeError, delattr, a, s)
2336+
2337+
2338+
def test_multiarray_flags_not_writable_attribute_deletion(self):
2339+
a = np.ones(2).flags
2340+
attr = ["contiguous", "c_contiguous", "f_contiguous", "fortran",
2341+
"owndata", "fnc", "forc", "behaved", "carray", "farray",
2342+
"num"]
2343+
for s in attr:
2344+
assert_raises(AttributeError, delattr, a, s)
2345+
2346+
2347+
def test_flat_element_deletion():
2348+
it = np.ones(3).flat
2349+
try:
2350+
del it[1]
2351+
del it[1:2]
2352+
except TypeError:
2353+
pass
2354+
except:
2355+
raise AssertionError
2356+
2357+
23212358
if __name__ == "__main__":
23222359
run_module_suite()

numpy/core/tests/test_na.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,5 +186,13 @@ def test_na_other_operations():
186186
assert_equal((np.NA | False).dtype, np.array(False).dtype)
187187
assert_equal((np.NA & True).dtype, np.array(True).dtype)
188188

189+
190+
def test_na_writable_attributes_deletion():
191+
a = np.NA(2)
192+
attr = ['payload', 'dtype']
193+
for s in attr:
194+
assert_raises(AttributeError, delattr, a, s)
195+
196+
189197
if __name__ == "__main__":
190198
run_module_suite()

0 commit comments

Comments
 (0)
0