8000 Merge pull request #12112 from mattip/get_field-offset-check · shoyer/numpy@8a560b9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8a560b9

Browse files
authored
Merge pull request numpy#12112 from mattip/get_field-offset-check
ENH: check getfield arguments to prevent invalid memory access
2 parents fb58c06 + 300e9f1 commit 8a560b9

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

doc/release/1.16.0-notes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,4 +209,9 @@ Previously `np.core.umath` and `np.core.multiarray` were the c-extension
209209
modules, they are now python wrappers to the single `np.core/_multiarray_math`
210210
c-extension module.
211211

212+
``getfield`` validity checks extended
213+
----------------------------------------
214+
`numpy.ndarray.getfield` now checks the dtype and offset arguments to prevent
215+
accessing invalid memory locations.
216+
212217
.. _`NEP 15` : http://www.numpy.org/neps/nep-0015-merge-multiarray-umath.html

numpy/core/src/multiarray/methods.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ PyArray_GetField(PyArrayObject *self, PyArray_Descr *typed, int offset)
356356
PyObject *ret = NULL;
357357
PyObject *safe;
358358
static PyObject *checkfunc = NULL;
359+
int self_elsize, typed_elsize;
359360

360361
/* check that we are not reinterpreting memory containing Objects. */
361362
if (_may_have_objects(PyArray_DESCR(self)) || _may_have_objects(typed)) {
@@ -373,6 +374,22 @@ PyArray_GetField(PyArrayObject *self, PyArray_Descr *typed, int offset)
373374
}
374375
Py_DECREF(safe);
375376
}
377+
self_elsize = PyArray_ITEMSIZE(self);
378+
typed_elsize = typed->elsize;
379+
380+
/* check that values are valid */
381+
if (typed_elsize > self_elsize) {
382+
PyErr_SetString(PyExc_ValueError, "new type is larger than original type");
383+
return NULL;
384+
}
385+
if (offset < 0) {
386+
PyErr_SetString(PyExc_ValueError, "offset is negative");
387+
return NULL;
388+
}
389+
if (offset > self_elsize - typed_elsize) {
390+
PyErr_SetString(PyExc_ValueError, "new type plus offset is larger than original type");
391+
return NULL;
392+
}
376393

377394
ret = PyArray_NewFromDescr_int(
378395
Py_TYPE(self), typed,

numpy/core/tests/test_multiarray.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7662,3 +7662,19 @@ def test_uintalignment_and_alignment():
76627662
# check that copy code doesn't complain in debug mode
76637663
dst = np.zeros((2,2), dtype='c8')
76647664
dst[:,1] = src[:,1] # assert in lowlevel_strided_loops fails?
7665+
7666+
def test_getfield():
7667+
a = np.arange(32, dtype='uint16')
7668+
if sys.byteorder == 'little':
7669+
i = 0
7670+
j = 1
7671+
else:
7672+
i = 1
7673+
j = 0
7674+
b = a.getfield('int8', i)
7675+
assert_equal(b, a)
7676+
b = a.getfield('int8', j)
7677+
assert_equal(b, 0)
7678+
pytest.raises(ValueError, a.getfield, 'uint8', -1)
7679+
pytest.raises(ValueError, a.getfield, 'uint8', 16)
7680+
pytest.raises(ValueError, a.getfield, 'uint64', 0)

0 commit comments

Comments
 (0)
0