]> granicus.if.org Git - python/commitdiff
Make the various iterators' "setstate" sliently and consistently clip the
authorKristján Valur Jónsson <sweskman@gmail.com>
Wed, 5 Mar 2014 13:47:57 +0000 (13:47 +0000)
committerKristján Valur Jónsson <sweskman@gmail.com>
Wed, 5 Mar 2014 13:47:57 +0000 (13:47 +0000)
index.  This avoids the possibility of setting an iterator to an invalid
state.

Lib/test/test_range.py
Modules/arraymodule.c
Objects/bytearrayobject.c
Objects/bytesobject.c
Objects/listobject.c
Objects/rangeobject.c
Objects/tupleobject.c
Objects/unicodeobject.c

index 063f320bfe6cd71b3bc8fcbf82dd9cf652e43e70..aab98abf4da6b85353153868d4bd693648fbcf9d 100644 (file)
@@ -380,6 +380,18 @@ class RangeTest(unittest.TestCase):
                 self.assertEqual(list(it), data[1:])
 
     def test_exhausted_iterator_pickling(self):
+        r = range(2**65, 2**65+2)
+        i = iter(r)
+        while True:
+            r = next(i)
+            if r == 2**65+1:
+                break
+        d = pickle.dumps(i)
+        i2 = pickle.loads(d)
+        self.assertEqual(list(i), [])
+        self.assertEqual(list(i2), [])
+
+    def test_large_exhausted_iterator_pickling(self):
         r = range(20)
         i = iter(r)
         while True:
index 96c9e5bba75f9d253216b219b56163e228691a3a..3aba9adbeb2c80692a7072df63a0cdc4d4ac77b5 100644 (file)
@@ -2798,6 +2798,8 @@ arrayiter_setstate(arrayiterobject *it, PyObject *state)
         return NULL;
     if (index < 0)
         index = 0;
+    else if (index > Py_SIZE(it->ao))
+        index = Py_SIZE(it->ao); /* iterator exhausted */
     it->index = index;
     Py_RETURN_NONE;
 }
index 60b281179d9ba91ae86311eb67fcf01c30928bfd..50667a646a331de87f0108e23c84c68f58d83983 100644 (file)
@@ -3043,9 +3043,13 @@ bytearrayiter_setstate(bytesiterobject *it, PyObject *state)
     Py_ssize_t index = PyLong_AsSsize_t(state);
     if (index == -1 && PyErr_Occurred())
         return NULL;
-    if (index < 0)
-        index = 0;
-    it->it_index = index;
+    if (it->it_seq != NULL) {
+        if (index < 0)
+            index = 0;
+        else if (index > PyByteArray_GET_SIZE(it->it_seq))
+            index = PyByteArray_GET_SIZE(it->it_seq); /* iterator exhausted */
+        it->it_index = index;
+    }
     Py_RETURN_NONE;
 }
 
index 9dcb74e8fdb264abbed9a6363c1c30ede4aaf1d3..f6d16dafdb52a9da0fb26db01cceb207aab9449c 100644 (file)
@@ -2996,9 +2996,13 @@ striter_setstate(striterobject *it, PyObject *state)
     Py_ssize_t index = PyLong_AsSsize_t(state);
     if (index == -1 && PyErr_Occurred())
         return NULL;
-    if (index < 0)
-        index = 0;
-    it->it_index = index;
+    if (it->it_seq != NULL) {
+        if (index < 0)
+            index = 0;
+        else if (index > PyBytes_GET_SIZE(it->it_seq))
+            index = PyBytes_GET_SIZE(it->it_seq); /* iterator exhausted */
+        it->it_index = index;
+    }
     Py_RETURN_NONE;
 }
 
index 6e0d094154e49205f94dec9499b2a5a132cc1274..143c7b3788356cffe8724199c287fbc3519511b1 100644 (file)
@@ -2803,6 +2803,8 @@ listiter_setstate(listiterobject *it, PyObject *state)
     if (it->it_seq != NULL) {
         if (index < 0)
             index = 0;
+        else if (index > PyList_GET_SIZE(it->it_seq))
+            index = PyList_GET_SIZE(it->it_seq); /* iterator exhausted */
         it->it_index = index;
     }
     Py_RETURN_NONE;
index 4b218b89617f3cddf2616019fd80d8b28be66d28..f2030c3cd2a7c7bcd40249360b92494fe53b0acd 100644 (file)
@@ -1000,10 +1000,11 @@ rangeiter_setstate(rangeiterobject *r, PyObject *state)
     long index = PyLong_AsLong(state);
     if (index == -1 && PyErr_Occurred())
         return NULL;
-    if (index < 0 || index > r->len) {
-        PyErr_SetString(PyExc_ValueError, "index out of range");
-        return NULL;
-    }
+    /* silently clip the index value */
+    if (index < 0)
+        index = 0;
+    else if (index > r->len)
+        index = r->len; /* exhausted iterator */
     r->index = index;
     Py_RETURN_NONE;
 }
@@ -1178,6 +1179,28 @@ longrangeiter_reduce(longrangeiterobject *r)
 static PyObject *
 longrangeiter_setstate(longrangeiterobject *r, PyObject *state)
 {
+    int cmp;
+   
+    /* clip the value */
+    PyObject *zero = PyLong_FromLong(0);
+    if (zero == NULL)
+        return NULL;
+    cmp = PyObject_RichCompareBool(state, zero, Py_LT);
+    if (cmp > 0) {
+        Py_CLEAR(r->index);
+        r->index = zero;
+        Py_RETURN_NONE;
+    }
+    Py_DECREF(zero);
+    if (cmp < 0)
+        return NULL;
+
+    cmp = PyObject_RichCompareBool(r->len, state, Py_LT);
+    if (cmp < 0)
+        return NULL;
+    if (cmp > 0)
+        state = r->len;
+    
     Py_CLEAR(r->index);
     r->index = state;
     Py_INCREF(r->index);
index 123df8cef3c21b292ca7932c7021affcba6997cd..f81559504fcb49dbce9deeec9a20afc5a75901db 100644 (file)
@@ -998,8 +998,8 @@ tupleiter_setstate(tupleiterobject *it, PyObject *state)
     if (it->it_seq != NULL) {
         if (index < 0)
             index = 0;
-        else if (it->it_seq != NULL && index > PyTuple_GET_SIZE(it->it_seq))
-            index = PyTuple_GET_SIZE(it->it_seq);
+        else if (index > PyTuple_GET_SIZE(it->it_seq))
+            index = PyTuple_GET_SIZE(it->it_seq); /* exhausted iterator */
         it->it_index = index;
     }
     Py_RETURN_NONE;
index 03007531bd8149e66550b5e6111aa80ebd76e1d4..4085d22b7168e72c8f22d184455370d855961eda 100644 (file)
@@ -14420,9 +14420,13 @@ unicodeiter_setstate(unicodeiterobject *it, PyObject *state)
     Py_ssize_t index = PyLong_AsSsize_t(state);
     if (index == -1 && PyErr_Occurred())
         return NULL;
-    if (index < 0)
-        index = 0;
-    it->it_index = index;
+    if (it->it_seq != NULL) {
+        if (index < 0)
+            index = 0;
+        else if (index > PyUnicode_GET_LENGTH(it->it_seq))
+            index = PyUnicode_GET_LENGTH(it->it_seq); /* iterator truncated */
+        it->it_index = index;
+    }
     Py_RETURN_NONE;
 }