diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2015-12-25 19:05:35 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2015-12-25 19:05:35 (GMT) |
commit | f9253c96fdff3ae1fcdacc72c06632f41df0424c (patch) | |
tree | 85e1a5bea8c837974ea404ac031894f85c4394bd /Objects | |
parent | ef1585eb9a488ae8ce3ff057f43a7048b941cc1c (diff) | |
parent | f81be8aa3ff3cbae66686482219bd7c7561f3de8 (diff) | |
download | cpython-f9253c96fdff3ae1fcdacc72c06632f41df0424c.zip cpython-f9253c96fdff3ae1fcdacc72c06632f41df0424c.tar.gz cpython-f9253c96fdff3ae1fcdacc72c06632f41df0424c.tar.bz2 |
Issue #22995: Instances of extension types with a state that aren't
subclasses of list or dict and haven't implemented any pickle-related
methods (__reduce__, __reduce_ex__, __getnewargs__, __getnewargs_ex__,
or __getstate__), can no longer be pickled. Including memoryview.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/typeobject.c | 51 |
1 files changed, 36 insertions, 15 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 2e75ec3..4fac9e8 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3839,7 +3839,7 @@ _PyType_GetSlotNames(PyTypeObject *cls) } Py_LOCAL(PyObject *) -_PyObject_GetState(PyObject *obj) +_PyObject_GetState(PyObject *obj, int required) { PyObject *state; PyObject *getstate; @@ -3854,6 +3854,13 @@ _PyObject_GetState(PyObject *obj) } PyErr_Clear(); + if (required && obj->ob_type->tp_itemsize) { + PyErr_Format(PyExc_TypeError, + "can't pickle %.200s objects", + Py_TYPE(obj)->tp_name); + return NULL; + } + { PyObject **dict; dict = _PyObject_GetDictPtr(obj); @@ -3878,6 +3885,24 @@ _PyObject_GetState(PyObject *obj) } assert(slotnames == Py_None || PyList_Check(slotnames)); + if (required) { + Py_ssize_t basicsize = PyBaseObject_Type.tp_basicsize; + if (obj->ob_type->tp_dictoffset) + basicsize += sizeof(PyObject *); + if (obj->ob_type->tp_weaklistoffset) + basicsize += sizeof(PyObject *); + if (slotnames != Py_None) + basicsize += sizeof(PyObject *) * Py_SIZE(slotnames); + if (obj->ob_type->tp_basicsize > basicsize) { + Py_DECREF(slotnames); + Py_DECREF(state); + PyErr_Format(PyExc_TypeError, + "can't pickle %.200s objects", + Py_TYPE(obj)->tp_name); + return NULL; + } + } + if (slotnames != Py_None && Py_SIZE(slotnames) > 0) { PyObject *slots; Py_ssize_t slotnames_size, i; @@ -4107,29 +4132,24 @@ reduce_newobj(PyObject *obj) PyObject *copyreg; PyObject *newobj, *newargs, *state, *listitems, *dictitems; PyObject *result; + int hasargs; if (Py_TYPE(obj)->tp_new == NULL) { PyErr_Format(PyExc_TypeError, - "can't pickle %s objects", + "can't pickle %.200s objects", Py_TYPE(obj)->tp_name); return NULL; } if (_PyObject_GetNewArguments(obj, &args, &kwargs) < 0) return NULL; - if (args == NULL) { - args = PyTuple_New(0); - if (args == NULL) { - Py_XDECREF(kwargs); - return NULL; - } - } copyreg = import_copyreg(); if (copyreg == NULL) { - Py_DECREF(args); + Py_XDECREF(args); Py_XDECREF(kwargs); return NULL; } + hasargs = (args != NULL); if (kwargs == NULL || PyDict_Size(kwargs) == 0) { _Py_IDENTIFIER(__newobj__); PyObject *cls; @@ -4139,13 +4159,13 @@ reduce_newobj(PyObject *obj) newobj = _PyObject_GetAttrId(copyreg, &PyId___newobj__); Py_DECREF(copyreg); if (newobj == NULL) { - Py_DECREF(args); + Py_XDECREF(args); return NULL; } - n = PyTuple_GET_SIZE(args); + n = args ? PyTuple_GET_SIZE(args) : 0; newargs = PyTuple_New(n+1); if (newargs == NULL) { - Py_DECREF(args); + Py_XDECREF(args); Py_DECREF(newobj); return NULL; } @@ -4157,7 +4177,7 @@ reduce_newobj(PyObject *obj) Py_INCREF(v); PyTuple_SET_ITEM(newargs, i+1, v); } - Py_DECREF(args); + Py_XDECREF(args); } else { _Py_IDENTIFIER(__newobj_ex__); @@ -4178,7 +4198,8 @@ reduce_newobj(PyObject *obj) } } - state = _PyObject_GetState(obj); + state = _PyObject_GetState(obj, + !hasargs && !PyList_Check(obj) && !PyDict_Check(obj)); if (state == NULL) { Py_DECREF(newobj); Py_DECREF(newargs); |