diff options
author | Sebastian Berg <sebastian@sipsolutions.net> | 2013-08-05 19:36:58 +0200 |
---|---|---|
committer | Sebastian Berg <sebastian@sipsolutions.net> | 2013-08-05 19:46:50 +0200 |
commit | f0910a18f164f0a71590003c24992eca90e34b61 (patch) | |
tree | b0ffc559e661b7aa1710e085c22366711824e774 | |
parent | 645b9f572f0a22e9049fd736b8b91427be2c8402 (diff) | |
download | numpy-f0910a18f164f0a71590003c24992eca90e34b61.tar.gz |
BUG: Boolean assignment allowed writing to 0-sized array
This was because of the assumption that broadcasting works
if the dimension is not > 1, but correct is != 1.
Adepted from a patch provided by prossahl.
Closes gh-3458.
-rw-r--r-- | numpy/core/src/multiarray/mapping.c | 4 | ||||
-rw-r--r-- | numpy/core/tests/test_indexing.py | 23 |
2 files changed, 19 insertions, 8 deletions
diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c index 8b3e5b5a9..25f3dad9b 100644 --- a/numpy/core/src/multiarray/mapping.c +++ b/numpy/core/src/multiarray/mapping.c @@ -806,8 +806,7 @@ array_ass_boolean_subscript(PyArrayObject *self, } /* Tweak the strides for 0-dim and broadcasting cases */ - if (PyArray_NDIM(v) > 0 && PyArray_DIMS(v)[0] > 1) { - v_stride = PyArray_STRIDES(v)[0]; + if (PyArray_NDIM(v) > 0 && PyArray_DIMS(v)[0] != 1) { if (size != PyArray_DIMS(v)[0]) { PyErr_Format(PyExc_ValueError, "NumPy boolean array indexing assignment " @@ -816,6 +815,7 @@ array_ass_boolean_subscript(PyArrayObject *self, (int)PyArray_DIMS(v)[0], (int)size); return -1; } + v_stride = PyArray_STRIDES(v)[0]; } else { v_stride = 0; diff --git a/numpy/core/tests/test_indexing.py b/numpy/core/tests/test_indexing.py index fa44900c7..3c74bc466 100644 --- a/numpy/core/tests/test_indexing.py +++ b/numpy/core/tests/test_indexing.py @@ -84,7 +84,7 @@ class TestIndexing(TestCase): assert_equal(a[np.array(False)], a[0]) def test_boolean_indexing_onedim(self): - # Indexing a 2-dimensional array with + # Indexing a 2-dimensional array with # boolean array of length one a = np.array([[ 0., 0., 0.]]) b = np.array([ True], dtype=bool) @@ -93,8 +93,19 @@ class TestIndexing(TestCase): a[b] = 1. assert_equal(a, [[1., 1., 1.]]) + def test_boolean_assignment_value_mismatch(self): + # A boolean assignment should fail when the shape of the values + # cannot be broadcasted to the subscription. (see also gh-3458) + a = np.arange(4) + def f(a, v): + a[a > -1] = v + + assert_raises(ValueError, f, a, []) + assert_raises(ValueError, f, a, [1, 2, 3]) + assert_raises(ValueError, f, a[:1], [1, 2, 3]) + def test_boolean_indexing_twodim(self): - # Indexing a 2-dimensional array with + # Indexing a 2-dimensional array with # 2-dimensional boolean array a = np.array([[1, 2, 3], [4 ,5, 6], @@ -116,7 +127,7 @@ class TestIndexing(TestCase): class TestMultiIndexingAutomated(TestCase): """ These test use code to mimic the C-Code indexing for selection. - + NOTE: * This still lacks tests for complex item setting. * If you change behavoir of indexing, you might want to modify these tests to try more combinations. @@ -160,7 +171,7 @@ class TestMultiIndexingAutomated(TestCase): def _get_multi_index(self, arr, indices): """Mimic multi dimensional indexing. - + Parameters ---------- arr : ndarray @@ -185,7 +196,7 @@ class TestMultiIndexingAutomated(TestCase): in_indices = list(indices) indices = [] # if False, this is a fancy or boolean index - no_copy = True + no_copy = True # number of fancy/scalar indexes that are not consecutive num_fancy = 0 # number of dimensions indexed by a "fancy" index @@ -487,7 +498,7 @@ class TestMultiIndexingAutomated(TestCase): self._check_multi_index(self.b, index) # Check very simple item getting: self._check_multi_index(self.a, (0,0,0,0)) - self._check_multi_index(self.b, (0,0,0,0)) + self._check_multi_index(self.b, (0,0,0,0)) # Also check (simple cases of) too many indices: assert_raises(IndexError, self.a.__getitem__, (0,0,0,0,0)) assert_raises(IndexError, self.a.__setitem__, (0,0,0,0,0), 0) |