fix accidental double wrap-around of negative indices in pop() optimisation
authorStefan Behnel <stefan_ml@behnel.de>
Sat, 16 Feb 2013 19:58:52 +0000 (20:58 +0100)
committerStefan Behnel <stefan_ml@behnel.de>
Sat, 16 Feb 2013 19:58:52 +0000 (20:58 +0100)
Cython/Utility/Optimize.c
tests/run/list_pop.pyx

index d6216d6..6a39b4f 100644 (file)
@@ -90,14 +90,15 @@ static PyObject* __Pyx_PyObject_PopIndex(PyObject* L, Py_ssize_t ix) {
     if (likely(PyList_CheckExact(L))) {
         Py_ssize_t size = PyList_GET_SIZE(L);
         if (likely(size > (((PyListObject*)L)->allocated >> 1))) {
-            if (ix < 0) {
-                ix += size;
+            Py_ssize_t cix = ix;
+            if (cix < 0) {
+                cix += size;
             }
-            if (likely(0 <= ix && ix < size)) {
-                PyObject* v = PyList_GET_ITEM(L, ix);
+            if (likely(0 <= cix && cix < size)) {
+                PyObject* v = PyList_GET_ITEM(L, cix);
                 Py_SIZE(L) -= 1;
                 size -= 1;
-                memmove(&PyList_GET_ITEM(L, ix), &PyList_GET_ITEM(L, ix+1), (size-ix)*sizeof(PyObject*));
+                memmove(&PyList_GET_ITEM(L, cix), &PyList_GET_ITEM(L, cix+1), (size-cix)*sizeof(PyObject*));
                 return v;
             }
         }
index 8ab5e2c..2e365da 100644 (file)
@@ -24,7 +24,6 @@ def simple_pop(L):
     []
     >>> simple_pop(L)
     Traceback (most recent call last):
-    ...
     IndexError: pop from empty list
 
     >>> simple_pop(A())
@@ -50,7 +49,6 @@ def simple_pop_typed(list L):
     []
     >>> simple_pop_typed(L)
     Traceback (most recent call last):
-    ...
     IndexError: pop from empty list
     """
     return L.pop()
@@ -63,17 +61,18 @@ def index_pop(L, int i):
     >>> L = list(range(10))
     >>> index_pop(L, 2)
     2
+    >>> index_pop(L, -10)
+    Traceback (most recent call last):
+    IndexError: pop index out of range
     >>> index_pop(L, -2)
     8
     >>> L
     [0, 1, 3, 4, 5, 6, 7, 9]
     >>> index_pop(L, 100)
     Traceback (most recent call last):
-    ...
     IndexError: pop index out of range
     >>> index_pop(L, -100)
     Traceback (most recent call last):
-    ...
     IndexError: pop index out of range
 
     >>> while L:
@@ -84,7 +83,6 @@ def index_pop(L, int i):
 
     >>> index_pop(L, 0)
     Traceback (most recent call last):
-    ...
     IndexError: pop from empty list
 
     >>> index_pop(A(), 3)
@@ -105,11 +103,9 @@ def index_pop_typed(list L, int i):
     [0, 1, 3, 4, 5, 6, 7, 9]
     >>> index_pop_typed(L, 100)
     Traceback (most recent call last):
-    ...
     IndexError: pop index out of range
     >>> index_pop_typed(L, -100)
     Traceback (most recent call last):
-    ...
     IndexError: pop index out of range
 
     >>> while L:
@@ -120,7 +116,6 @@ def index_pop_typed(list L, int i):
 
     >>> index_pop_typed(L, 0)
     Traceback (most recent call last):
-    ...
     IndexError: pop from empty list
     """
     return L.pop(i)
@@ -143,7 +138,6 @@ def index_pop_literal(list L):
 
     >>> index_pop_literal(L)
     Traceback (most recent call last):
-    ...
     IndexError: pop from empty list
     """
     return L.pop(0)