From 7efef9dca97304e048038193fdf1c69b56ecc10a Mon Sep 17 00:00:00 2001 From: Allan Haldane Date: Wed, 21 Sep 2016 21:22:55 -0400 Subject: BUG: non-integers can end up in dtype offsets Fix is to convert offsets to python ints at dtype creation. Fixes #8059 --- numpy/core/src/multiarray/common.c | 1 + numpy/core/src/multiarray/descriptor.c | 17 ++++++++++++++--- numpy/core/tests/test_dtype.py | 15 +++++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) (limited to 'numpy/core') 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): -- cgit v1.2.1