summaryrefslogtreecommitdiffstats
path: root/Modules/_pickle.c
diff options
context:
space:
mode:
authorAmaury Forgeot d'Arc <amauryfa@gmail.com>2008-10-30 22:25:31 (GMT)
committerAmaury Forgeot d'Arc <amauryfa@gmail.com>2008-10-30 22:25:31 (GMT)
commit424b4819bea4b63d9d88fe55812e64a32f3c0e7d (patch)
tree7ca587c1f1e7094505230ab8cd6f5c0f9c8a98da /Modules/_pickle.c
parent6a27efa2d321c2b262c0cab3c2d4af3e2e8a9ead (diff)
downloadcpython-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.c44
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);