Skip to content
Browse files

BUG: Fix indexing 0-sized arrays using empty fancy-indexes

Due to subspace creation for fancy indexing selecting the 0s
element on every fancy dimension, this failed if the dimension
was empty. Propagating check_index to disable the unnecessary
check in this case.
  • Loading branch information...
1 parent 6ffa2ea commit 29c8ae8d042117e192938e8782a24646f8146e94 @seberg committed Oct 30, 2012
View
6 numpy/core/src/multiarray/iterators.c
@@ -97,7 +97,8 @@ NPY_NO_EXPORT int
parse_index(PyArrayObject *self, PyObject *op,
npy_intp *out_dimensions,
npy_intp *out_strides,
- npy_intp *out_offset)
+ npy_intp *out_offset,
+ int check_index)
{
int i, j, n;
int nd_old, nd_new, n_add, n_ellipsis;
@@ -136,7 +137,8 @@ parse_index(PyArrayObject *self, PyObject *op,
start = parse_index_entry(op1, &step_size, &n_steps,
nd_old < PyArray_NDIM(self) ?
PyArray_DIMS(self)[nd_old] : 0,
- nd_old, nd_old < PyArray_NDIM(self));
+ nd_old, check_index ?
+ nd_old < PyArray_NDIM(self) : 0);
Py_DECREF(op1);
if (start == -1) {
break;
View
3 numpy/core/src/multiarray/iterators.h
@@ -9,7 +9,8 @@ NPY_NO_EXPORT int
parse_index(PyArrayObject *self, PyObject *op,
npy_intp *out_dimensions,
npy_intp *out_strides,
- npy_intp *out_offset);
+ npy_intp *out_offset,
+ int check_index);
NPY_NO_EXPORT PyObject
*iter_subscript(PyArrayIterObject *, PyObject *);
View
20 numpy/core/src/multiarray/mapping.c
@@ -25,7 +25,7 @@
#define SOBJ_LISTTUP 4
static PyObject *
-array_subscript_simple(PyArrayObject *self, PyObject *op);
+array_subscript_simple(PyArrayObject *self, PyObject *op, int check_index);
/******************************************************************************
*** IMPLEMENT MAPPING PROTOCOL ***
@@ -556,7 +556,7 @@ fancy_indexing_check(PyObject *args)
*/
NPY_NO_EXPORT PyObject *
-array_subscript_simple(PyArrayObject *self, PyObject *op)
+array_subscript_simple(PyArrayObject *self, PyObject *op, int check_index)
{
npy_intp dimensions[NPY_MAXDIMS], strides[NPY_MAXDIMS];
npy_intp offset;
@@ -601,7 +601,7 @@ array_subscript_simple(PyArrayObject *self, PyObject *op)
/* Standard (view-based) Indexing */
nd = parse_index(self, op, dimensions,
- strides, &offset);
+ strides, &offset, check_index);
if (nd == -1) {
return NULL;
}
@@ -1222,7 +1222,7 @@ array_subscript_fromobject(PyArrayObject *self, PyObject *op)
return array_subscript_fancy(self, op, fancy);
}
else {
- return array_subscript_simple(self, op);
+ return array_subscript_simple(self, op, 1);
}
}
@@ -1256,9 +1256,10 @@ array_subscript(PyArrayObject *self, PyObject *op)
ret = array_subscript_fancy(self, op, fancy);
}
else {
- ret = array_subscript_simple(self, op);
+ ret = array_subscript_simple(self, op, 1);
}
}
+
if (ret == NULL) {
return NULL;
}
@@ -1301,7 +1302,7 @@ array_ass_sub_simple(PyArrayObject *self, PyObject *ind, PyObject *op)
/* Rest of standard (view-based) indexing */
if (PyArray_CheckExact(self)) {
- tmp = (PyArrayObject *)array_subscript_simple(self, ind);
+ tmp = (PyArrayObject *)array_subscript_simple(self, ind, 1);
if (tmp == NULL) {
return -1;
}
@@ -1839,20 +1840,21 @@ PyArray_MapIterBind(PyArrayMapIterObject *mit, PyArrayObject *arr)
/*
* all indexing arrays have been converted to 0
* therefore we can extract the subspace with a simple
- * getitem call which will use view semantics
+ * getitem call which will use view semantics, but
+ * without index checking.
*
* But, be sure to do it with a true array.
*/
if (PyArray_CheckExact(arr)) {
- sub = array_subscript_simple(arr, mit->indexobj);
+ sub = array_subscript_simple(arr, mit->indexobj, 0);
}
else {
Py_INCREF(arr);
obj = PyArray_EnsureArray((PyObject *)arr);
if (obj == NULL) {
goto fail;
}
- sub = array_subscript_simple((PyArrayObject *)obj, mit->indexobj);
+ sub = array_subscript_simple((PyArrayObject *)obj, mit->indexobj, 0);
Py_DECREF(obj);
}

2 comments on commit 29c8ae8

@seberg
Owner
seberg commented on 29c8ae8 Apr 14, 2013

Was thinking about how to fix the array conversion stuff to get list of bools right and also deprecate the non-integer lists, but I just realized that this is not quite correct. It should work usually, but if someone creates an object that can not be converted to an integer array, but works for normal indexing, the bounds checking will be broken...

@seberg
Owner
seberg commented on 29c8ae8 Apr 14, 2013

I guess it is not be a huge issue, since you should need an object providing __index__ (or maybe __int__ on py2) but not __long__ (__int__ on Py3). But its not ideal, thinking about a sentinal... but I am starting to wonder about actually redoing the index parsing...

Please sign in to comment.
Something went wrong with that request. Please try again.