mirror of
https://github.com/python/cpython.git
synced 2025-08-03 16:39:00 +00:00
Merged revisions 67049 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r67049 | amaury.forgeotdarc | 2008-10-30 22:18:34 +0100 (jeu., 30 oct. 2008) | 8 lines Issue #4176: Pickle would crash the interpreter when a __reduce__ function does not return an iterator for the 4th and 5th items. (sequence-like and mapping-like state) A list is not an iterator... Will backport to 2.6 and 2.5. ........
This commit is contained in:
parent
6a27efa2d3
commit
424b4819be
3 changed files with 47 additions and 16 deletions
|
@ -1961,8 +1961,9 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
|
|||
PyObject *callable;
|
||||
PyObject *argtup;
|
||||
PyObject *state = NULL;
|
||||
PyObject *listitems = NULL;
|
||||
PyObject *dictitems = NULL;
|
||||
PyObject *listitems = Py_None;
|
||||
PyObject *dictitems = Py_None;
|
||||
Py_ssize_t size;
|
||||
|
||||
int use_newobj = self->proto >= 2;
|
||||
|
||||
|
@ -1970,27 +1971,48 @@ save_reduce(PicklerObject *self, PyObject *args, PyObject *obj)
|
|||
const char build_op = BUILD;
|
||||
const char newobj_op = NEWOBJ;
|
||||
|
||||
size = PyTuple_Size(args);
|
||||
if (size < 2 || size > 5) {
|
||||
PyErr_SetString(PicklingError, "tuple returned by "
|
||||
"__reduce__ must contain 2 through 5 elements");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!PyArg_UnpackTuple(args, "save_reduce", 2, 5,
|
||||
&callable, &argtup, &state, &listitems, &dictitems))
|
||||
return -1;
|
||||
|
||||
if (!PyCallable_Check(callable)) {
|
||||
PyErr_SetString(PicklingError,
|
||||
"first argument of save_reduce() must be callable");
|
||||
PyErr_SetString(PicklingError, "first item of the tuple "
|
||||
"returned by __reduce__ must be callable");
|
||||
return -1;
|
||||
}
|
||||
if (!PyTuple_Check(argtup)) {
|
||||
PyErr_SetString(PicklingError,
|
||||
"second argument of save_reduce() must be a tuple");
|
||||
PyErr_SetString(PicklingError, "second item of the tuple "
|
||||
"returned by __reduce__ must be a tuple");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (state == Py_None)
|
||||
state = NULL;
|
||||
|
||||
if (listitems == Py_None)
|
||||
listitems = NULL;
|
||||
else if (!PyIter_Check(listitems)) {
|
||||
PyErr_Format(PicklingError, "Fourth element of tuple"
|
||||
"returned by __reduce__ must be an iterator, not %s",
|
||||
Py_TYPE(listitems)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dictitems == Py_None)
|
||||
dictitems = NULL;
|
||||
else if (!PyIter_Check(dictitems)) {
|
||||
PyErr_Format(PicklingError, "Fifth element of tuple"
|
||||
"returned by __reduce__ must be an iterator, not %s",
|
||||
Py_TYPE(dictitems)->tp_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Protocol 2 special case: if callable's name is __newobj__, use
|
||||
NEWOBJ. */
|
||||
|
@ -2309,16 +2331,6 @@ save(PicklerObject *self, PyObject *obj, int pers_save)
|
|||
"__reduce__ must return a string or tuple");
|
||||
goto error;
|
||||
}
|
||||
if (Py_SIZE(reduce_value) < 2 || Py_SIZE(reduce_value) > 5) {
|
||||
PyErr_SetString(PicklingError, "tuple returned by __reduce__ "
|
||||
"must contain 2 through 5 elements");
|
||||
goto error;
|
||||
}
|
||||
if (!PyTuple_Check(PyTuple_GET_ITEM(reduce_value, 1))) {
|
||||
PyErr_SetString(PicklingError, "second item of the tuple "
|
||||
"returned by __reduce__ must be a tuple");
|
||||
goto error;
|
||||
}
|
||||
|
||||
status = save_reduce(self, reduce_value, obj);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue