cpython: 3b2c28061184 (original) (raw)
Mercurial > cpython
changeset 89477:3b2c28061184 3.3
Make the various iterators' "setstate" sliently and consistently clip the index. This avoids the possibility of setting an iterator to an invalid state.
Kristján Valur Jónsson sweskman@gmail.com | |
---|---|
date | Wed, 05 Mar 2014 13:47:57 +0000 |
parents | 24d4e52f4f87 |
children | 08cf35d4ef49 52743dc788e6 |
files | 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 |
diffstat | 8 files changed, 66 insertions(+), 15 deletions(-)[+] [-] Lib/test/test_range.py 12 Modules/arraymodule.c 2 Objects/bytearrayobject.c 10 Objects/bytesobject.c 10 Objects/listobject.c 2 Objects/rangeobject.c 31 Objects/tupleobject.c 4 Objects/unicodeobject.c 10 |
line wrap: on
line diff
--- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -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)[](#l1.7)
i = iter(r)[](#l1.8)
while True:[](#l1.9)
r = next(i)[](#l1.10)
if r == 2**65+1:[](#l1.11)
break[](#l1.12)
d = pickle.dumps(i)[](#l1.13)
i2 = pickle.loads(d)[](#l1.14)
self.assertEqual(list(i), [])[](#l1.15)
self.assertEqual(list(i2), [])[](#l1.16)
--- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -2798,6 +2798,8 @@ arrayiter_setstate(arrayiterobject *it, return NULL; if (index < 0) index = 0;
- else if (index > Py_SIZE(it->ao))
it->index = index; Py_RETURN_NONE; }index = Py_SIZE(it->ao); /* iterator exhausted */[](#l2.8)
--- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -3043,9 +3043,13 @@ bytearrayiter_setstate(bytesiterobject * Py_ssize_t index = PyLong_AsSsize_t(state); if (index == -1 && PyErr_Occurred()) return NULL;
- if (it->it_seq != NULL) {
if (index < 0)[](#l3.11)
index = 0;[](#l3.12)
else if (index > PyByteArray_GET_SIZE(it->it_seq))[](#l3.13)
index = PyByteArray_GET_SIZE(it->it_seq); /* iterator exhausted */[](#l3.14)
it->it_index = index;[](#l3.15)
- } Py_RETURN_NONE; }
--- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -2996,9 +2996,13 @@ striter_setstate(striterobject *it, PyOb Py_ssize_t index = PyLong_AsSsize_t(state); if (index == -1 && PyErr_Occurred()) return NULL;
- if (it->it_seq != NULL) {
if (index < 0)[](#l4.11)
index = 0;[](#l4.12)
else if (index > PyBytes_GET_SIZE(it->it_seq))[](#l4.13)
index = PyBytes_GET_SIZE(it->it_seq); /* iterator exhausted */[](#l4.14)
it->it_index = index;[](#l4.15)
- } Py_RETURN_NONE; }
--- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -2803,6 +2803,8 @@ listiter_setstate(listiterobject *it, Py if (it->it_seq != NULL) { if (index < 0) index = 0;
else if (index > PyList_GET_SIZE(it->it_seq))[](#l5.7)
} Py_RETURN_NONE;index = PyList_GET_SIZE(it->it_seq); /* iterator exhausted */[](#l5.8) it->it_index = index;[](#l5.9)
--- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -1000,10 +1000,11 @@ rangeiter_setstate(rangeiterobject *r, P 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");[](#l6.8)
return NULL;[](#l6.9)
- }
- /* silently clip the index value */
- if (index < 0)
index = 0;[](#l6.13)
- else if (index > r->len)
r->index = index; Py_RETURN_NONE; } @@ -1178,6 +1179,28 @@ longrangeiter_reduce(longrangeiterobject static PyObject * longrangeiter_setstate(longrangeiterobject *r, PyObject *state) {index = r->len; /* exhausted iterator */[](#l6.15)
- int cmp;
- /* clip the value */
- PyObject *zero = PyLong_FromLong(0);
- if (zero == NULL)
return NULL;[](#l6.28)
- cmp = PyObject_RichCompareBool(state, zero, Py_LT);
- if (cmp > 0) {
Py_CLEAR(r->index);[](#l6.31)
r->index = zero;[](#l6.32)
Py_RETURN_NONE;[](#l6.33)
- }
- Py_DECREF(zero);
- if (cmp < 0)
return NULL;[](#l6.37)
- cmp = PyObject_RichCompareBool(r->len, state, Py_LT);
- if (cmp < 0)
return NULL;[](#l6.41)
- if (cmp > 0)
state = r->len;[](#l6.43)
- Py_CLEAR(r->index); r->index = state; Py_INCREF(r->index);
--- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -998,8 +998,8 @@ tupleiter_setstate(tupleiterobject *it, if (it->it_seq != NULL) { if (index < 0) index = 0;
else if (it->it_seq != NULL && index > PyTuple_GET_SIZE(it->it_seq))[](#l7.7)
index = PyTuple_GET_SIZE(it->it_seq);[](#l7.8)
else if (index > PyTuple_GET_SIZE(it->it_seq))[](#l7.9)
} Py_RETURN_NONE;index = PyTuple_GET_SIZE(it->it_seq); /* exhausted iterator */[](#l7.10) it->it_index = index;[](#l7.11)
--- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -14420,9 +14420,13 @@ unicodeiter_setstate(unicodeiterobject * Py_ssize_t index = PyLong_AsSsize_t(state); if (index == -1 && PyErr_Occurred()) return NULL;