summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
authorPauli Virtanen <pav@iki.fi>2010-10-10 20:09:20 +0200
committerPauli Virtanen <pav@iki.fi>2010-10-10 20:09:20 +0200
commita16ee31eab9d75d86b2fde2ea4d6787b5f61ea9e (patch)
tree446496fedd5cf66fa69a692f9695858f7927fe50 /numpy
parent2be89147998f59371077b684096ae226f7294ab2 (diff)
downloadnumpy-a16ee31eab9d75d86b2fde2ea4d6787b5f61ea9e.tar.gz
BUG: core: fix duplicate name problems in dtype.names setting (#1598)
Diffstat (limited to 'numpy')
-rw-r--r--numpy/core/src/multiarray/descriptor.c27
-rw-r--r--numpy/core/tests/test_regression.py6
2 files changed, 26 insertions, 7 deletions
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c
index 74cb7da7a..f635e1c48 100644
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -1828,6 +1828,7 @@ arraydescr_names_set(PyArray_Descr *self, PyObject *val)
int N = 0;
int i;
PyObject *new_names;
+ PyObject *new_fields;
if (self->names == NULL) {
PyErr_SetString(PyExc_ValueError,
"there are no fields defined");
@@ -1857,26 +1858,38 @@ arraydescr_names_set(PyArray_Descr *self, PyObject *val)
}
/* Update dictionary keys in fields */
new_names = PySequence_Tuple(val);
+ new_fields = PyDict_New();
for (i = 0; i < N; i++) {
PyObject *key;
PyObject *item;
PyObject *new_key;
+ int ret;
key = PyTuple_GET_ITEM(self->names, i);
- /* Borrowed reference to item */
+ /* Borrowed references to item and new_key */
item = PyDict_GetItem(self->fields, key);
- /* Hold on to it even through DelItem */
- Py_INCREF(item);
new_key = PyTuple_GET_ITEM(new_names, i);
- PyDict_DelItem(self->fields, key);
- PyDict_SetItem(self->fields, new_key, item);
- /* self->fields now holds reference */
- Py_DECREF(item);
+ /* Check for duplicates */
+ ret = PyDict_Contains(new_fields, new_key);
+ if (ret != 0) {
+ if (ret < 0) {
+ PyErr_Clear();
+ }
+ PyErr_SetString(PyExc_ValueError, "Duplicate field names given.");
+ Py_DECREF(new_names);
+ Py_DECREF(new_fields);
+ return -1;
+ }
+ PyDict_SetItem(new_fields, new_key, item);
}
/* Replace names */
Py_DECREF(self->names);
self->names = new_names;
+ /* Replace fields */
+ Py_DECREF(self->fields);
+ self->fields = new_fields;
+
return 0;
}
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index 249a0a3a6..52548ca1a 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -1420,5 +1420,11 @@ class TestRegression(TestCase):
x = 2**64 - 1
assert_equal(int(np.uint64(x)), x)
+ def test_duplicate_field_names_assign(self):
+ ra = np.fromiter(((i*3, i*2) for i in xrange(10)), dtype='i8,f8')
+ ra.dtype.names = ('f1', 'f2')
+ rep = repr(ra) # should not cause a segmentation fault
+ assert_raises(ValueError, setattr, ra.dtype, 'names', ('f1', 'f1'))
+
if __name__ == "__main__":
run_module_suite()