diff options
| author | Amaury Forgeot d'Arc <amauryfa@gmail.com> | 2009-01-12 23:36:55 +0000 |
|---|---|---|
| committer | Amaury Forgeot d'Arc <amauryfa@gmail.com> | 2009-01-12 23:36:55 +0000 |
| commit | a40d57366432cd65915b92fe3e6bfe1d5ad63be0 (patch) | |
| tree | 45ef11eae7d47a373fea86cba4b1b0c4902bb93a /Objects | |
| parent | f94d7fa5fb90df0163cffca2864885a7da49d4f6 (diff) | |
| download | cpython-git-a40d57366432cd65915b92fe3e6bfe1d5ad63be0.tar.gz | |
#3720: Interpreter crashes when an evil iterator removes its own next function.
Now the slot is filled with a function that always raises.
Will not backport: extensions compiled with 2.6.x would not run on 2.6.0.
Diffstat (limited to 'Objects')
| -rw-r--r-- | Objects/abstract.c | 1 | ||||
| -rw-r--r-- | Objects/object.c | 14 | ||||
| -rw-r--r-- | Objects/typeobject.c | 6 |
3 files changed, 19 insertions, 2 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c index 956c4f4996..80a1289138 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -3067,7 +3067,6 @@ PyObject * PyIter_Next(PyObject *iter) { PyObject *result; - assert(PyIter_Check(iter)); result = (*iter->ob_type->tp_iternext)(iter); if (result == NULL && PyErr_Occurred() && diff --git a/Objects/object.c b/Objects/object.c index 1e0db4ac69..ba736a9d93 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1305,6 +1305,20 @@ PyObject_SelfIter(PyObject *obj) return obj; } +/* Helper used when the __next__ method is removed from a type: + tp_iternext is never NULL and can be safely called without checking + on every iteration. + */ + +PyObject * +_PyObject_NextNotImplemented(PyObject *self) +{ + PyErr_Format(PyExc_TypeError, + "'%.200s' object is not iterable", + Py_TYPE(self)->tp_name); + return NULL; +} + /* Generic GetAttr functions - put these in your tp_[gs]etattro slot */ PyObject * diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 3f790e8824..8242242d19 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6090,8 +6090,12 @@ update_one_slot(PyTypeObject *type, slotdef *p) } do { descr = _PyType_Lookup(type, p->name_strobj); - if (descr == NULL) + if (descr == NULL) { + if (ptr == (void**)&type->tp_iternext) { + specific = _PyObject_NextNotImplemented; + } continue; + } if (Py_TYPE(descr) == &PyWrapperDescr_Type) { void **tptr = resolve_slotdups(type, p->name_strobj); if (tptr == NULL || tptr == ptr) |
