diff --git a/src/pymor/vectorarrays/block.py b/src/pymor/vectorarrays/block.py
index 3aa9eb29a..9fdb31fbd 100644
--- a/src/pymor/vectorarrays/block.py
+++ b/src/pymor/vectorarrays/block.py
@@ -65,6 +65,9 @@ class BlockVectorArray(VectorArray):
             return 0
 
     def __getitem__(self, ind):
+        if isinstance(ind, Number) and (ind >= len(self) or ind < -len(self)):
+            raise IndexError('VectorArray index out of range')
+        assert self.check_ind(ind)
         return BlockVectorArrayView(self, ind)
 
     def __delitem__(self, ind):
diff --git a/src/pymor/vectorarrays/interface.py b/src/pymor/vectorarrays/interface.py
index f2871ef06..7825d088a 100644
--- a/src/pymor/vectorarrays/interface.py
+++ b/src/pymor/vectorarrays/interface.py
@@ -664,14 +664,22 @@ class VectorArray(BasicObject):
         return len({i if i >= 0 else l+i for i in ind})
 
     def normalize_ind(self, ind):
-        """Normalize given indices such that they are independent of the array length."""
+        """Normalize given indices such that they are independent of the array length.
+
+        Does not check validity of the indices.
+        """
+        l = len(self)
         if type(ind) is slice:
-            return slice(*ind.indices(len(self)))
+            start, stop, step = ind.indices(l)
+            if start == stop:
+                return slice(0, 0, 1)
+            assert start >= 0
+            assert stop >= 0 or (step < 0 and stop >= -1)
+            return slice(start, None if stop == -1 else stop, step)
         elif not hasattr(ind, '__len__'):
-            ind = ind if 0 <= ind else len(self)+ind
+            ind = ind if 0 <= ind else l+ind
             return slice(ind, ind+1)
         else:
-            l = len(self)
             return [i if 0 <= i else l+i for i in ind]
 
     def sub_index(self, ind, ind_ind):
diff --git a/src/pymor/vectorarrays/list.py b/src/pymor/vectorarrays/list.py
index 8537648dd..23bd976bc 100644
--- a/src/pymor/vectorarrays/list.py
+++ b/src/pymor/vectorarrays/list.py
@@ -385,6 +385,7 @@ class ListVectorArray(VectorArray):
     def __getitem__(self, ind):
         if isinstance(ind, Number) and (ind >= len(self) or ind < -len(self)):
             raise IndexError('VectorArray index out of range')
+        assert self.check_ind(ind)
         return ListVectorArrayView(self, ind)
 
     def __delitem__(self, ind):
diff --git a/src/pymor/vectorarrays/mpi.py b/src/pymor/vectorarrays/mpi.py
index 9bb24aa4f..64dbb0c3e 100644
--- a/src/pymor/vectorarrays/mpi.py
+++ b/src/pymor/vectorarrays/mpi.py
@@ -13,6 +13,8 @@ The implementations are based on the event loop provided
 by :mod:`pymor.tools.mpi`.
 """
 
+from numbers import Number
+
 import numpy as np
 
 from pymor.core.pickle import unpicklable
@@ -54,12 +56,16 @@ class MPIVectorArray(VectorArray):
         return mpi.call(mpi.method_call, self.obj_id, '__len__')
 
     def __getitem__(self, ind):
+        if isinstance(ind, Number) and (ind >= len(self) or ind < -len(self)):
+            raise IndexError('VectorArray index out of range')
+        assert self.check_ind(ind)
         U = type(self)(mpi.call(mpi.method_call_manage, self.obj_id, '__getitem__', ind),
                        self.space)
         U.is_view = True
         return U
 
     def __delitem__(self, ind):
+        assert self.check_ind(ind)
         mpi.call(mpi.method_call, self.obj_id, '__delitem__', ind)
 
     def copy(self, deep=False):
diff --git a/src/pymor/vectorarrays/numpy.py b/src/pymor/vectorarrays/numpy.py
index e4e2c0981..67de3d149 100644
--- a/src/pymor/vectorarrays/numpy.py
+++ b/src/pymor/vectorarrays/numpy.py
@@ -70,6 +70,7 @@ class NumpyVectorArray(VectorArray):
     def __getitem__(self, ind):
         if isinstance(ind, Number) and (ind >= self._len or ind < -self._len):
             raise IndexError('VectorArray index out of range')
+        assert self.check_ind(ind)
         return NumpyVectorArrayView(self, ind)
 
     def __delitem__(self, ind):
@@ -451,7 +452,6 @@ class NumpyVectorArrayView(NumpyVectorArray):
     is_view = True
 
     def __init__(self, array, ind):
-        assert array.check_ind(ind)
         self.base = array
         self.ind = array.normalize_ind(ind)
         self.space = array.space

diff --git a/src/pymortests/strategies.py b/src/pymortests/strategies.py
index 07ad9d0b6..0f17d2542 100644
--- a/src/pymortests/strategies.py
+++ b/src/pymortests/strategies.py
@@ -254,20 +254,15 @@ def valid_inds(v, length=None, random_module=None):
         yield []
 
 
-# TODO: remove old assumptions on slice values
-def _filtered_slices(length):
-    def _filter(sl):
-        return sl.step is None or sl.step > 0
-    return hyst.slices(length).filter(_filter)
-
-
 @hyst.composite
 def valid_indices(draw, array_strategy, length=None):
     v = draw(array_strategy)
     ints = hyst.integers(min_value=-len(v), max_value=max(len(v)-1, 0))
     indices = hyst.nothing()
     if length is None:
-        indices = indices | hyst.just([]) | hyst.lists(ints, max_size=2*len(v)) | _filtered_slices(len(v))
+        indices = indices | hyst.just([]) | hyst.lists(ints, max_size=2*len(v))
+    else:
+        indices = indices | hyst.slices(length)
     if len(v) > 0:
         inds = [-len(v), 0, len(v) - 1]
         if len(v) == length:
@@ -317,13 +312,13 @@ def st_valid_inds_of_same_length(draw, v1, v2):
     # `| hynp.integer_array_indices(shape=(LEN_X,))`
     if len1 == len2:
         ints = hyst.integers(min_value=-len1, max_value=max(len1 - 1, 0))
-        slicer = _filtered_slices(len1) | hyst.lists(ints, max_size=len1)
+        slicer = hyst.slices(len1) | hyst.lists(ints, max_size=len1)
         ret = ret | hyst.tuples(hyst.shared(slicer, key="st_valid_inds_of_same_length"),
                                 hyst.shared(slicer, key="st_valid_inds_of_same_length"))
     if len1 > 0 and len2 > 0:
         mlen = min(len1, len2)
         ints = hyst.integers(min_value=-mlen, max_value=max(mlen - 1, 0))
-        slicer = _filtered_slices(mlen) | ints | hyst.lists(ints, max_size=mlen)
+        slicer = hyst.slices(mlen) | ints | hyst.lists(ints, max_size=mlen)
         ret = ret | hyst.tuples(hyst.shared(slicer, key="st_valid_inds_of_same_length_uneven"),
                                 hyst.shared(slicer, key="st_valid_inds_of_same_length_uneven"))
     return draw(ret)
@@ -383,8 +378,8 @@ def st_valid_inds_of_different_length(draw, v1, v2):
 
     len1, len2 = len(v1), len(v2)
     # TODO we should include integer arrays here
-    val1 = _filtered_slices(len1)  # | hynp.integer_array_indices(shape=(len1,))
-    val2 = _filtered_slices(len2)  # | hynp.integer_array_indices(shape=(len1,))
+    val1 = hyst.slices(len1)  # | hynp.integer_array_indices(shape=(len1,))
+    val2 = hyst.slices(len2)  # | hynp.integer_array_indices(shape=(len1,))
     ret = hyst.tuples(val1, val2).filter(_filter)
     return draw(ret)
 
diff --git a/src/pymortests/vectorarray.py b/src/pymortests/vectorarray.py
index 28a0c972c..ad462ce85 100644
--- a/src/pymortests/vectorarray.py
+++ b/src/pymortests/vectorarray.py
@@ -315,6 +315,15 @@ def test_copy_repeated_index(vector_array):
             pass
 
 
+@pyst.given_vector_arrays(index_strategy=pyst.valid_indices)
+def test_normalize_ind(vectors_and_indices):
+    v, ind = vectors_and_indices
+    assert v.check_ind(ind)
+    normalized = v.normalize_ind(ind)
+    assert v.len_ind(normalized) == v.len_ind(ind)
+    assert v.len_ind_unique(normalized) == v.len_ind_unique(ind)
+
+
 @pyst.given_vector_arrays(count=2, index_strategy=pyst.pairs_both_lengths)
 def test_append(vectors_and_indices):
     (v1, v2), (_, ind) = vectors_and_indices

Remove slicing restrictions for vectorarray tests
Historically index tests were performed with a set of manually constructed `slice` objects. When rewriting the tests to instead draw slices from a hypothesis strategy it became necessary to add a filter to mimic the properties of the manual examples, or be drowned by test failures. Notably this filter excludes negative step sizes. It's unclear whether the assertions simply are defective or if real failures are among them. And I currently do not have time to look into this further. Anybody interested should check out the `vectorarray_tests_unrestricted_slicing` branch and run the tests there. 
src/pymortests/vectorarray.py::test_inner_self src/pymortests/vectorarray.py::test_axpy_self
src/pymortests/vectorarray.py::test_sub_incompatible src/pymortests/vectorarray.py::test_scla src/pymortests/vectorarray.py::test_imul src/pymortests/vectorarray.py::test_add_incompatible src/pymortests/vectorarray.py::test_axpy src/pymortests/vectorarray.py::test_normalize_ind src/pymortests/vectorarray.py::test_random_normal src/pymortests/vectorarray.py::test_COW src/pymortests/vectorarray.py::test_zeros src/pymortests/vectorarray.py::test_norm2 src/pymortests/vectorarray.py::test_wrong_ind_raises_exception src/pymortests/vectorarray.py::test_del src/pymortests/vectorarray.py::test_norm src/pymortests/vectorarray.py::test_lincomb_2d src/pymortests/vectorarray.py::test_dofs src/pymortests/vectorarray.py::test_pairwise_inner_incompatible src/pymortests/vectorarray.py::test_append_self src/pymortests/vectorarray.py::test_axpy_incompatible src/pymortests/vectorarray.py::test_copy_repeated_index src/pymortests/vectorarray.py::test_iadd src/pymortests/vectorarray.py::test_append src/pymortests/vectorarray.py::test_axpy_wrong_coefficients src/pymortests/vectorarray.py::test_iter src/pymortests/vectorarray.py::test_mul_wrong_factor src/pymortests/vectorarray.py::test_isub src/pymortests/vectorarray.py::test_amax src/pymortests/vectorarray.py::test_from_numpy src/pymortests/vectorarray.py::test_sub src/pymortests/vectorarray.py::test_lincomb_wrong_coefficients src/pymortests/vectorarray.py::test_inner src/pymortests/vectorarray.py::test_imul_wrong_factor src/pymortests/vectorarray.py::test_full src/pymortests/vectorarray.py::test_axpy_one_x src/pymortests/vectorarray.py::test_lincomb_1d src/pymortests/vectorarray.py::test_add src/pymortests/vectorarray.py::test_print src/pymortests/vectorarray.py::test_append_incompatible src/pymortests/vectorarray.py::test_sup_norm src/pymortests/vectorarray.py::test_scal_wrong_coefficients src/pymortests/vectorarray.py::test_empty src/pymortests/vectorarray.py::test_random_uniform src/pymortests/vectorarray.py::test_gramian src/pymortests/vectorarray.py::test_neg src/pymortests/vectorarray.py::test_inner_incompatible src/pymortests/vectorarray.py::test_space src/pymortests/vectorarray.py::test_getitem_repeated src/pymortests/vectorarray.py::test_isub_incompatible src/pymortests/vectorarray.py::test_copy src/pymortests/vectorarray.py::test_shape src/pymortests/vectorarray.py::test_pickle src/pymortests/vectorarray.py::test_pairwise_inner_self src/pymortests/vectorarray.py::test_iadd_incompatible src/pymortests/vectorarray.py::test_components_wrong_dof_indices src/pymortests/vectorarray.py::test_mul src/pymortests/vectorarray.py::test_pairwise_inner src/pymortests/vectorarray.py::test_ones