From a4163c4f3f003813a799850a1bd1b8cb5e58f49a Mon Sep 17 00:00:00 2001 From: Henning Dickten Date: Wed, 26 Nov 2014 17:19:19 +0100 Subject: [PATCH 1/2] BUG: Closes #5313 PyArray_AsCArray caused segfault --- numpy/core/src/multiarray/multiarraymodule.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index 2a685cc74ef7..8446e1583ab8 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -220,7 +220,7 @@ PyArray_AsCArray(PyObject **op, void *ptr, npy_intp *dims, int nd, goto fail; } for (i = 0; i < n; i++) { - ptr3[i] = ptr3[n + (m-1)*i]; + ptr3[i] = (char **) &ptr3[n + m * i]; for (j = 0; j < m; j++) { ptr3[i][j] = PyArray_BYTES(ap) + i*PyArray_STRIDES(ap)[0] + j*PyArray_STRIDES(ap)[1]; } From b32b097037d09026052db1553b633592e8985f62 Mon Sep 17 00:00:00 2001 From: Henning Dickten Date: Mon, 1 Dec 2014 00:25:50 +0100 Subject: [PATCH 2/2] TST: added test for PyArray_AsCArray #5313 --- .../src/multiarray/multiarray_tests.c.src | 78 +++++++++++++++++++ numpy/core/tests/test_multiarray.py | 19 ++++- 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/numpy/core/src/multiarray/multiarray_tests.c.src b/numpy/core/src/multiarray/multiarray_tests.c.src index bd0366bd5db9..8de29e7bf290 100644 --- a/numpy/core/src/multiarray/multiarray_tests.c.src +++ b/numpy/core/src/multiarray/multiarray_tests.c.src @@ -719,6 +719,81 @@ array_indexing(PyObject *NPY_UNUSED(self), PyObject *args) return NULL; } +/* + * Test C-api PyArray_AsCArray item getter + */ +static PyObject * +test_as_c_array(PyObject *NPY_UNUSED(self), PyObject *args) +{ + PyArrayObject *array_obj; + npy_intp dims[3]; // max 3-dim + npy_intp i=0, j=0, k=0; + npy_intp num_dims = 0; + PyArray_Descr *descr = NULL; + double *array1 = NULL; + double **array2 = NULL; + double ***array3 = NULL; + double temp = 9999; + + if (!PyArg_ParseTuple(args, "O!l|ll", + &PyArray_Type, &array_obj, + &i, &j, &k)) { + return NULL; + } + + if (NULL == array_obj) { + return NULL; + } + + num_dims = PyArray_NDIM(array_obj); + descr = PyArray_DESCR(array_obj); + + switch (num_dims) { + case 1: + if (PyArray_AsCArray( + (PyObject **) &array_obj, + (void *) &array1, + dims, + 1, + descr) < 0) { + PyErr_SetString(PyExc_RuntimeError, "error converting 1D array"); + return NULL; + } + temp = array1[i]; + PyArray_Free((PyObject *) array_obj, (void *) array1); + break; + case 2: + if (PyArray_AsCArray( + (PyObject **) &array_obj, + (void **) &array2, + dims, + 2, + descr) < 0) { + PyErr_SetString(PyExc_RuntimeError, "error converting 2D array"); + return NULL; + } + temp = array2[i][j]; + PyArray_Free((PyObject *) array_obj, (void *) array2); + break; + case 3: + if (PyArray_AsCArray( + (PyObject **) &array_obj, + (void ***) &array3, + dims, + 3, + descr) < 0) { + PyErr_SetString(PyExc_RuntimeError, "error converting 3D array"); + return NULL; + } + temp = array3[i][j][k]; + PyArray_Free((PyObject *) array_obj, (void *) array3); + break; + default: + PyErr_SetString(PyExc_ValueError, "array.ndim not in [1, 3]"); + return NULL; + } + return Py_BuildValue("f", temp); +} /* * Test nditer of too large arrays using remove axis, etc. @@ -850,6 +925,9 @@ static PyMethodDef Multiarray_TestsMethods[] = { {"array_indexing", array_indexing, METH_VARARGS, NULL}, + {"test_as_c_array", + test_as_c_array, + METH_VARARGS, NULL}, {"test_nditer_too_large", test_nditer_too_large, METH_VARARGS, NULL}, diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index aa18864545df..d472a9569307 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -22,7 +22,7 @@ from numpy.core.multiarray_tests import ( test_neighborhood_iterator, test_neighborhood_iterator_oob, test_pydatamem_seteventhook_start, test_pydatamem_seteventhook_end, - test_inplace_increment, get_buffer_info + test_inplace_increment, get_buffer_info, test_as_c_array ) from numpy.testing import ( TestCase, run_module_suite, assert_, assert_raises, @@ -4201,6 +4201,23 @@ def test_mapiter(self): assert_equal(b, [ 100.1, 51., 6., 3., 4., 5. ]) +class TestAsCArray(TestCase): + def test_1darray(self): + array = np.arange(24, dtype=np.double) + from_c = test_as_c_array(array, 3) + assert_equal(array[3], from_c) + + def test_2darray(self): + array = np.arange(24, dtype=np.double).reshape(3, 8) + from_c = test_as_c_array(array, 2, 4) + assert_equal(array[2, 4], from_c) + + def test_3darray(self): + array = np.arange(24, dtype=np.double).reshape(2, 3, 4) + from_c = test_as_c_array(array, 1, 2, 3) + assert_equal(array[1, 2, 3], from_c) + + class PriorityNdarray(): __array_priority__ = 1000