diff --git a/pandas/_libs/internals.pyx b/pandas/_libs/internals.pyx index 4f27fde52414a..006fd34632d5a 100644 --- a/pandas/_libs/internals.pyx +++ b/pandas/_libs/internals.pyx @@ -207,7 +207,7 @@ cdef slice slice_canonize(slice s): Convert slice to canonical bounded form. """ cdef: - Py_ssize_t start = 0, stop = 0, step = 1, length + Py_ssize_t start = 0, stop = 0, step = 1 if s.step is None: step = 1 @@ -239,7 +239,7 @@ cdef slice slice_canonize(slice s): if stop > start: stop = start - if start < 0 or (stop < 0 and s.stop is not None): + if start < 0 or (stop < 0 and s.stop is not None and step > 0): raise ValueError("unbounded slice") if stop < 0: diff --git a/pandas/tests/internals/test_internals.py b/pandas/tests/internals/test_internals.py index 689cdbce103e6..8ee84803339df 100644 --- a/pandas/tests/internals/test_internals.py +++ b/pandas/tests/internals/test_internals.py @@ -922,6 +922,13 @@ def test_zero_step_raises(self, slc): with pytest.raises(ValueError, match=msg): BlockPlacement(slc) + def test_slice_canonize_negative_stop(self): + # GH#37524 negative stop is OK with negative step and positive start + slc = slice(3, -1, -2) + + bp = BlockPlacement(slc) + assert bp.indexer == slice(3, None, -2) + @pytest.mark.parametrize( "slc", [