From e6fc7401a92c7b51a80782d8095819b9909a0322 Mon Sep 17 00:00:00 2001
From: Mark Dickinson <dickinsm@gmail.com>
Date: Fri, 6 Aug 2010 18:55:26 +0000
Subject: In PySlice_IndicesEx, clip the step to [-PY_SSIZE_T_MAX,
 PY_SSIZE_T_MAX] rather than [PY_SSIZE_T_MIN, PY_SSIZE_T_MAX].

---
 Misc/NEWS             |  4 ++++
 Objects/sliceobject.c | 10 +++++++++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/Misc/NEWS b/Misc/NEWS
index 0567a20..bac8d00 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -529,6 +529,10 @@ Core and Builtins
 C-API
 -----
 
+- PySlice_GetIndicesEx now clips the step to [-PY_SSIZE_T_MAX, PY_SSIZE_T_MAX]
+  instead of [-PY_SSIZE_T_MAX-1, PY_SSIZE_T_MAX].  This makes it safe to do
+  "step = -step" when reversing a slice.
+
 - Issue #5753: A new C API function, `PySys_SetArgvEx`, allows embedders of the
   interpreter to set sys.argv without also modifying sys.path.  This helps fix
   `CVE-2008-5983
diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c
index ee89006..55fda52 100644
--- a/Objects/sliceobject.c
+++ b/Objects/sliceobject.c
@@ -131,7 +131,8 @@ PySlice_GetIndices(PySliceObject *r, Py_ssize_t length,
 
 int
 PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length,
-                     Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength)
+                     Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
+                     Py_ssize_t *slicelength)
 {
     /* this is harder to get right than you might think */
 
@@ -147,6 +148,13 @@ PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length,
                             "slice step cannot be zero");
             return -1;
         }
+        /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it
+         * with -PY_SSIZE_T_MAX.  This doesn't affect the semantics, and it
+         * guards against later undefined behaviour resulting from code that
+         * does "step = -step" as part of a slice reversal.
+         */
+        if (*step < -PY_SSIZE_T_MAX)
+            *step = -PY_SSIZE_T_MAX;
     }
 
     defstart = *step < 0 ? length-1 : 0;
-- 
cgit v0.12

