diff options
author | Amaury Forgeot d'Arc <amauryfa@gmail.com> | 2008-10-30 22:25:31 (GMT) |
---|---|---|
committer | Amaury Forgeot d'Arc <amauryfa@gmail.com> | 2008-10-30 22:25:31 (GMT) |
commit | 424b4819bea4b63d9d88fe55812e64a32f3c0e7d (patch) | |
tree | 7ca587c1f1e7094505230ab8cd6f5c0f9c8a98da /Modules/_pickle.c | |
parent | 6a27efa2d321c2b262c0cab3c2d4af3e2e8a9ead (diff) | |
download | cpython-424b4819bea4b63d9d88fe55812e64a32f3c0e7d.zip cpython-424b4819bea4b63d9d88fe55812e64a32f3c0e7d.tar.gz cpython-424b4819bea4b63d9d88fe55812e64a32f3c0e7d.tar.bz2 |
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.
........
Diffstat (limited to 'Modules/_pickle.c')
-rw-r--r-- | Modules/_pickle.c | 44 |
1 files changed, 28 insertions, 16 deletions
diff --git a/Modules/_pickle.c b/Modules/_pickle.c index 2b672a7..a689c33 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -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); |