Index: Lib/pickle.py =================================================================== --- Lib/pickle.py (revision 67065) +++ Lib/pickle.py (working copy) @@ -342,6 +342,9 @@ else: self.write(PERSID + str(pid) + '\n') + def _isiter(self, obj): + return hasattr(obj, 'next') and hasattr(obj, '__iter__') + def save_reduce(self, func, args, state=None, listitems=None, dictitems=None, obj=None): # This API is called by some subclasses @@ -354,6 +357,16 @@ if not hasattr(func, '__call__'): raise PicklingError("func from reduce should be callable") + # Assert that listitems is an iterator + if listitems is not None and not self._isiter(listitems): + raise PicklingError("listitems from save_reduce() should be an " + "iterator") + + # Assert that dictitems is an iterator + if dictitems is not None and not self._isiter(dictitems): + raise PicklingError("dictitems from save_reduce() should be an " + "iterator") + save = self.save write = self.write Index: Modules/cPickle.c =================================================================== --- Modules/cPickle.c (revision 67065) +++ Modules/cPickle.c (working copy) @@ -2213,7 +2213,6 @@ PyObject *state = NULL; PyObject *listitems = Py_None; PyObject *dictitems = Py_None; - Py_ssize_t size; int use_newobj = self->proto >= 2; @@ -2221,14 +2220,6 @@ static char build = BUILD; static char newobj = NEWOBJ; - size = PyTuple_Size(args); - if (size < 2 || size > 5) { - cPickle_ErrFormat(PicklingError, "tuple returned by " - "%s must contain 2 through 5 elements", - "O", fn); - return -1; - } - if (! PyArg_UnpackTuple(args, "save_reduce", 2, 5, &callable, &argtup, @@ -2389,6 +2380,7 @@ PyObject *py_ob_id = 0, *__reduce__ = 0, *t = 0; int res = -1; int tmp; + Py_ssize_t size; if (Py_EnterRecursiveCall(" while pickling an object")) return -1; @@ -2621,6 +2613,14 @@ goto finally; } + size = PyTuple_Size(t); + if (size < 2 || size > 5) { + cPickle_ErrFormat(PicklingError, "tuple returned by " + "%s must contain 2 through 5 elements", + "O", __reduce__); + goto finally; + } + res = save_reduce(self, t, __reduce__, args); finally: