diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2012-02-16 19:23:48 -0700 |
---|---|---|
committer | Charles Harris <charlesr.harris@gmail.com> | 2012-02-16 19:23:48 -0700 |
commit | b20a013ef99aadb87f7ce21648e1ebbc6623bd49 (patch) | |
tree | cdc79348d1c5d7bb165fd07d26f7e453c012ef66 | |
parent | ae3dd3304bc76dfe9f9514c922669feeb50e3073 (diff) | |
parent | 4ba819a9cb73cc6e55ac3ca4c13190460b145003 (diff) | |
download | numpy-b20a013ef99aadb87f7ce21648e1ebbc6623bd49.tar.gz |
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.
-rw-r--r-- | numpy/core/src/multiarray/descriptor.c | 5 | ||||
-rw-r--r-- | numpy/core/src/multiarray/flagsobject.c | 45 | ||||
-rw-r--r-- | numpy/core/src/multiarray/getset.c | 2 | ||||
-rw-r--r-- | numpy/core/src/multiarray/iterators.c | 6 | ||||
-rw-r--r-- | numpy/core/src/multiarray/na_object.c | 13 | ||||
-rw-r--r-- | numpy/core/src/multiarray/nditer_pywrap.c | 57 | ||||
-rw-r--r-- | numpy/core/tests/test_dtype.py | 18 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 41 | ||||
-rw-r--r-- | numpy/core/tests/test_na.py | 8 | ||||
-rw-r--r-- | numpy/core/tests/test_nditer.py | 28 |
10 files changed, 185 insertions, 38 deletions
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c index 3f2da284d..1bb439dcf 100644 --- a/numpy/core/src/multiarray/descriptor.c +++ b/numpy/core/src/multiarray/descriptor.c @@ -1807,6 +1807,11 @@ arraydescr_names_set(PyArray_Descr *self, PyObject *val) PyObject *new_names; PyObject *new_fields; + if (val == NULL) { + PyErr_SetString(PyExc_AttributeError, + "Cannot delete dtype names attribute"); + return -1; + } if (!PyDataType_HASFIELDS(self)) { PyErr_SetString(PyExc_ValueError, "there are no fields defined"); diff --git a/numpy/core/src/multiarray/flagsobject.c b/numpy/core/src/multiarray/flagsobject.c index 9ada8a26b..a633a2ac2 100644 --- a/numpy/core/src/multiarray/flagsobject.c +++ b/numpy/core/src/multiarray/flagsobject.c @@ -276,8 +276,14 @@ arrayflags_maskna_get(PyArrayFlagsObject *self) static int arrayflags_maskna_set(PyArrayFlagsObject *self, PyObject *obj) { + if (obj == NULL) { + PyErr_SetString(PyExc_AttributeError, + "Cannot delete flags maskna attribute"); + return -1; + } if (self->arr == NULL) { - PyErr_SetString(PyExc_ValueError, "Cannot set flags on array scalars."); + PyErr_SetString(PyExc_ValueError, + "Cannot set flags on array scalars."); return -1; } @@ -287,7 +293,7 @@ arrayflags_maskna_set(PyArrayFlagsObject *self, PyObject *obj) else { if (self->flags & NPY_ARRAY_MASKNA) { PyErr_SetString(PyExc_ValueError, - "Cannot remove a NumPy array's NA mask"); + "Cannot remove a NumPy array's NA mask"); return -1; } else { @@ -313,8 +319,14 @@ arrayflags_ownmaskna_get(PyArrayFlagsObject *self) static int arrayflags_ownmaskna_set(PyArrayFlagsObject *self, PyObject *obj) { + if (obj == NULL) { + PyErr_SetString(PyExc_AttributeError, + "Cannot delete flags ownmaskna attributes"); + return -1; + } if (self->arr == NULL) { - PyErr_SetString(PyExc_ValueError, "Cannot set flags on array scalars."); + PyErr_SetString(PyExc_ValueError, + "Cannot set flags on array scalars."); return -1; } @@ -338,8 +350,15 @@ static int arrayflags_updateifcopy_set(PyArrayFlagsObject *self, PyObject *obj) { PyObject *res; + + if (obj == NULL) { + PyErr_SetString(PyExc_AttributeError, + "Cannot delete flags updateifcopy attribute"); + return -1; + } if (self->arr == NULL) { - PyErr_SetString(PyExc_ValueError, "Cannot set flags on array scalars."); + PyErr_SetString(PyExc_ValueError, + "Cannot set flags on array scalars."); return -1; } res = PyObject_CallMethod(self->arr, "setflags", "OOO", Py_None, Py_None, @@ -355,8 +374,15 @@ static int arrayflags_aligned_set(PyArrayFlagsObject *self, PyObject *obj) { PyObject *res; + + if (obj == NULL) { + PyErr_SetString(PyExc_AttributeError, + "Cannot delete flags aligned attribute"); + return -1; + } if (self->arr == NULL) { - PyErr_SetString(PyExc_ValueError, "Cannot set flags on array scalars."); + PyErr_SetString(PyExc_ValueError, + "Cannot set flags on array scalars."); return -1; } res = PyObject_CallMethod(self->arr, "setflags", "OOO", Py_None, @@ -373,8 +399,15 @@ static int arrayflags_writeable_set(PyArrayFlagsObject *self, PyObject *obj) { PyObject *res; + + if (obj == NULL) { + PyErr_SetString(PyExc_AttributeError, + "Cannot delete flags writeable attribute"); + return -1; + } if (self->arr == NULL) { - PyErr_SetString(PyExc_ValueError, "Cannot set flags on array scalars."); + PyErr_SetString(PyExc_ValueError, + "Cannot set flags on array scalars."); return -1; } res = PyObject_CallMethod(self->arr, "setflags", "OOO", diff --git a/numpy/core/src/multiarray/getset.c b/numpy/core/src/multiarray/getset.c index 14042c9af..d3146dc5c 100644 --- a/numpy/core/src/multiarray/getset.c +++ b/numpy/core/src/multiarray/getset.c @@ -941,7 +941,7 @@ NPY_NO_EXPORT PyGetSetDef array_getsetlist[] = { (getter)array_ctypes_get, NULL, NULL, NULL}, - { "T", + {"T", (getter)array_transpose_get, NULL, NULL, NULL}, diff --git a/numpy/core/src/multiarray/iterators.c b/numpy/core/src/multiarray/iterators.c index 2c173e3e9..44163a0bd 100644 --- a/numpy/core/src/multiarray/iterators.c +++ b/numpy/core/src/multiarray/iterators.c @@ -1037,6 +1037,12 @@ iter_ass_subscript(PyArrayIterObject *self, PyObject *ind, PyObject *val) PyArray_CopySwapFunc *copyswap; + if (val == NULL) { + PyErr_SetString(PyExc_TypeError, + "Cannot delete iterator elements"); + return -1; + } + if (ind == Py_Ellipsis) { ind = PySlice_New(NULL, NULL, NULL); retval = iter_ass_subscript(self, ind, val); diff --git a/numpy/core/src/multiarray/na_object.c b/numpy/core/src/multiarray/na_object.c index ed319a348..45e199fbe 100644 --- a/numpy/core/src/multiarray/na_object.c +++ b/numpy/core/src/multiarray/na_object.c @@ -184,6 +184,12 @@ na_payload_set(NpyNA_fields *self, PyObject *value) { long payload; + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, + "Cannot delete NA payload attribute"); + return -1; + } + /* Don't allow changing the static singleton instance */ if (self->is_singleton) { PyErr_SetString(PyExc_RuntimeError, @@ -191,7 +197,7 @@ na_payload_set(NpyNA_fields *self, PyObject *value) "make a new copy like 'numpy.NA(payload)'"); return -1; } - else if (value == NULL || value == Py_None) { + else if (value == Py_None) { self->payload = NPY_NA_NOPAYLOAD; } else { @@ -241,6 +247,11 @@ na_dtype_set(NpyNA_fields *self, PyObject *value) { PyArray_Descr *dtype = NULL; + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, + "Cannot delete NA dtype attribute"); + return -1; + } /* Don't allow changing the static singleton instance */ if (self->is_singleton) { PyErr_SetString(PyExc_RuntimeError, diff --git a/numpy/core/src/multiarray/nditer_pywrap.c b/numpy/core/src/multiarray/nditer_pywrap.c index c0323c346..42d836633 100644 --- a/numpy/core/src/multiarray/nditer_pywrap.c +++ b/numpy/core/src/multiarray/nditer_pywrap.c @@ -1612,15 +1612,14 @@ npyiter_multi_index_set(NewNpyArrayIterObject *self, PyObject *value) { npy_intp idim, ndim, multi_index[NPY_MAXDIMS]; - if (self->iter == NULL) { - PyErr_SetString(PyExc_ValueError, - "Iterator is invalid"); + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, + "Cannot delete nditer multi_index"); return -1; } - - if (value == NULL) { + if (self->iter == NULL) { PyErr_SetString(PyExc_ValueError, - "Cannot delete the multi_index"); + "Iterator is invalid"); return -1; } @@ -1684,15 +1683,14 @@ static PyObject *npyiter_index_get(NewNpyArrayIterObject *self) static int npyiter_index_set(NewNpyArrayIterObject *self, PyObject *value) { - if (self->iter == NULL) { - PyErr_SetString(PyExc_ValueError, - "Iterator is invalid"); + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, + "Cannot delete nditer index"); return -1; } - - if (value == NULL) { + if (self->iter == NULL) { PyErr_SetString(PyExc_ValueError, - "Cannot delete index"); + "Iterator is invalid"); return -1; } @@ -1737,15 +1735,14 @@ static int npyiter_iterindex_set(NewNpyArrayIterObject *self, PyObject *value) { npy_intp iterindex; - if (self->iter == NULL) { - PyErr_SetString(PyExc_ValueError, - "Iterator is invalid"); + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, + "Cannot delete nditer iterindex"); return -1; } - - if (value == NULL) { + if (self->iter == NULL) { PyErr_SetString(PyExc_ValueError, - "Cannot delete iterindex"); + "Iterator is invalid"); return -1; } @@ -1799,15 +1796,14 @@ static int npyiter_iterrange_set(NewNpyArrayIterObject *self, PyObject *value) long istart = 0, iend = 0; #endif - if (self->iter == NULL) { - PyErr_SetString(PyExc_ValueError, - "Iterator is invalid"); + if (value == NULL) { + PyErr_SetString(PyExc_AttributeError, + "Cannot delete nditer iterrange"); return -1; } - - if (value == NULL) { + if (self->iter == NULL) { PyErr_SetString(PyExc_ValueError, - "Cannot delete iterrange"); + "Iterator is invalid"); return -1; } @@ -2173,8 +2169,8 @@ npyiter_seq_ass_item(NewNpyArrayIterObject *self, Py_ssize_t i, PyObject *v) if (v == NULL) { - PyErr_SetString(PyExc_ValueError, - "can't delete iterator operands"); + PyErr_SetString(PyExc_TypeError, + "Cannot delete iterator elements"); return -1; } @@ -2271,8 +2267,8 @@ npyiter_seq_ass_slice(NewNpyArrayIterObject *self, Py_ssize_t ilow, Py_ssize_t i; if (v == NULL) { - PyErr_SetString(PyExc_ValueError, - "cannot delete iterator elements"); + PyErr_SetString(PyExc_TypeError, + "Cannot delete iterator elements"); return -1; } @@ -2376,6 +2372,11 @@ static int npyiter_ass_subscript(NewNpyArrayIterObject *self, PyObject *op, PyObject *value) { + if (value == NULL) { + PyErr_SetString(PyExc_TypeError, + "Cannot delete iterator elements"); + return -1; + } if (self->iter == NULL || self->finished) { PyErr_SetString(PyExc_ValueError, "Iterator is past the end"); diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py index 3625d58b4..ba9de32ba 100644 --- a/numpy/core/tests/test_dtype.py +++ b/numpy/core/tests/test_dtype.py @@ -401,5 +401,23 @@ class TestString(TestCase): "dtype([('a', '<M8[D]'), ('b', '<m8[us]')])") +class TestDtypeAttributeDeletion(object): + + def test_dtype_non_writable_attributes_deletion(self): + dt = np.dtype(np.double) + attr = ["subdtype", "descr", "str", "name", "base", "shape", + "isbuiltin", "isnative", "isalignedstruct", "fields", + "metadata", "hasobject"] + for s in attr: + assert_raises(AttributeError, delattr, dt, s) + + + def test_dtype_writable_attributes_deletion(self): + dt = np.dtype(np.double) + attr = ["names"] + for s in attr: + assert_raises(AttributeError, delattr, dt, s) + + if __name__ == "__main__": run_module_suite() diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 6d402c3ec..086a38128 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -2309,14 +2309,51 @@ if sys.version_info >= (2, 6): class TestArrayAttributeDeletion(object): - """ticket #2046, should not seqfault, raise AttributeError""" - def test_attribute_deletion(self): + def test_multiarray_writable_attributes_deletion(self): + """ticket #2046, should not seqfault, raise AttributeError""" a = np.ones(2) attr = ['shape', 'strides', 'data', 'dtype', 'real', 'imag', 'flat'] for s in attr: assert_raises(AttributeError, delattr, a, s) + def test_multiarray_not_writable_attributes_deletion(self): + a = np.ones(2) + attr = ["ndim", "flags", "itemsize", "size", "nbytes", "base", + "ctypes", "T", "__array_interface__", "__array_struct__", + "__array_priority__", "__array_finalize__"] + for s in attr: + assert_raises(AttributeError, delattr, a, s) + + + def test_multiarray_flags_writable_attribute_deletion(self): + a = np.ones(2).flags + attr = ['updateifcopy', 'aligned', 'writeable', 'maskna', + 'ownmaskna'] + for s in attr: + assert_raises(AttributeError, delattr, a, s) + + + def test_multiarray_flags_not_writable_attribute_deletion(self): + a = np.ones(2).flags + attr = ["contiguous", "c_contiguous", "f_contiguous", "fortran", + "owndata", "fnc", "forc", "behaved", "carray", "farray", + "num"] + for s in attr: + assert_raises(AttributeError, delattr, a, s) + + +def test_flat_element_deletion(): + it = np.ones(3).flat + try: + del it[1] + del it[1:2] + except TypeError: + pass + except: + raise AssertionError + + if __name__ == "__main__": run_module_suite() diff --git a/numpy/core/tests/test_na.py b/numpy/core/tests/test_na.py index 2950598f8..eb92a0035 100644 --- a/numpy/core/tests/test_na.py +++ b/numpy/core/tests/test_na.py @@ -186,5 +186,13 @@ def test_na_other_operations(): assert_equal((np.NA | False).dtype, np.array(False).dtype) assert_equal((np.NA & True).dtype, np.array(True).dtype) + +def test_na_writable_attributes_deletion(): + a = np.NA(2) + attr = ['payload', 'dtype'] + for s in attr: + assert_raises(AttributeError, delattr, a, s) + + if __name__ == "__main__": run_module_suite() diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py index b0badc2d9..5bc3b8dee 100644 --- a/numpy/core/tests/test_nditer.py +++ b/numpy/core/tests/test_nditer.py @@ -2554,5 +2554,33 @@ def test_iter_maskna_default_use_maskna(): assert_(it.operands[2].flags.maskna) assert_array_equal(it.operands[2], a+b+1) + +def test_iter_writable_attribute_deletion(): + it = np.nditer(np.ones(2)) + attr = ["value", "shape", "operands", "itviews", "has_delayed_bufalloc", + "iterationneedsapi", "has_multi_index", "has_index", "dtypes", + "ndim", "nop", "itersize", "finished"] + for s in attr: + assert_raises(AttributeError, delattr, it, s) + + +def test_iter_non_writable_attribute_deletion(): + it = np.nditer(np.ones(2)) + attr = [ "multi_index", "index", "iterrange", "iterindex"] + for s in attr: + assert_raises(AttributeError, delattr, it, s) + + +def test_iter_element_deletion(): + it = np.nditer(np.ones(3)) + try: + del it[1] + del it[1:2] + except TypeError: + pass + except: + raise AssertionError + + if __name__ == "__main__": run_module_suite() |