summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Haldane <allan.haldane@gmail.com>2016-09-21 21:22:55 -0400
committerAllan Haldane <allan.haldane@gmail.com>2016-09-22 12:46:46 -0400
commit7efef9dca97304e048038193fdf1c69b56ecc10a (patch)
tree5ddec33f1de3f762b516b4764479106eb827526c
parente1ad72da79a97b0f2209d47d3f7c514ddcb0e8de (diff)
downloadnumpy-7efef9dca97304e048038193fdf1c69b56ecc10a.tar.gz
BUG: non-integers can end up in dtype offsets
Fix is to convert offsets to python ints at dtype creation. Fixes #8059
-rw-r--r--numpy/core/src/multiarray/common.c1
-rw-r--r--numpy/core/src/multiarray/descriptor.c17
-rw-r--r--numpy/core/tests/test_dtype.py15
3 files changed, 30 insertions, 3 deletions
diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c
index bd566b77b..dc9b2edec 100644
--- a/numpy/core/src/multiarray/common.c
+++ b/numpy/core/src/multiarray/common.c
@@ -867,6 +867,7 @@ _unpack_field(PyObject *value, PyArray_Descr **descr, npy_intp *offset)
*offset = PyLong_AsSsize_t(off);
}
else {
+ PyErr_SetString(PyExc_IndexError, "can't convert offset");
return -1;
}
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c
index fbfda72d7..c966440ac 100644
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -1071,8 +1071,19 @@ _convert_from_dict(PyObject *obj, int align)
if (!off) {
goto fail;
}
- offset = PyInt_AsLong(off);
- PyTuple_SET_ITEM(tup, 1, off);
+ offset = PyArray_PyIntAsInt(off);
+ if (offset == -1 && PyErr_Occurred()) {
+ Py_DECREF(off);
+ goto fail;
+ }
+ Py_DECREF(off);
+ if (offset < 0) {
+ PyErr_Format(PyExc_ValueError, "offset %d cannot be negative",
+ (int)offset);
+ goto fail;
+ }
+
+ PyTuple_SET_ITEM(tup, 1, PyInt_FromLong(offset));
/* Flag whether the fields are specified out of order */
if (offset < totalsize) {
has_out_of_order_fields = 1;
@@ -1186,7 +1197,7 @@ _convert_from_dict(PyObject *obj, int align)
if (tmp == NULL) {
PyErr_Clear();
} else {
- itemsize = (int)PyInt_AsLong(tmp);
+ itemsize = (int)PyArray_PyIntAsInt(tmp);
if (itemsize == -1 && PyErr_Occurred()) {
Py_DECREF(new);
return NULL;
diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py
index f0721d7a3..c52d480a7 100644
--- a/numpy/core/tests/test_dtype.py
+++ b/numpy/core/tests/test_dtype.py
@@ -272,6 +272,21 @@ class TestRecord(TestCase):
for n in d.names:
assert_equal(d.fields[n][0], np.dtype('?'))
+ def test_nonint_offsets(self):
+ # gh-8059
+ def make_dtype(off):
+ return np.dtype({'names': ['A'], 'formats': ['i4'],
+ 'offsets': [off]})
+
+ assert_raises(TypeError, make_dtype, 'ASD')
+ assert_raises(OverflowError, make_dtype, 2**70)
+ assert_raises(TypeError, make_dtype, 2.3)
+ assert_raises(ValueError, make_dtype, -10)
+
+ # no errors here:
+ dt = make_dtype(np.uint32(0))
+ np.zeros(1, dtype=dt)[0].item()
+
class TestSubarray(TestCase):
def test_single_subarray(self):