diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2015-12-25 19:04:29 (GMT) |
---|---|---|
committer | Serhiy Storchaka <storchaka@gmail.com> | 2015-12-25 19:04:29 (GMT) |
commit | f81be8aa3ff3cbae66686482219bd7c7561f3de8 (patch) | |
tree | dcb8278ffce4c41cff723c1a12b94218f4baf591 /Objects | |
parent | bc4ded953742bc4411faa3264505b4c61ac64827 (diff) | |
download | cpython-f81be8aa3ff3cbae66686482219bd7c7561f3de8.zip cpython-f81be8aa3ff3cbae66686482219bd7c7561f3de8.tar.gz cpython-f81be8aa3ff3cbae66686482219bd7c7561f3de8.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 5b858bd..f3c0c38 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3831,7 +3831,7 @@ _PyType_GetSlotNames(PyTypeObject *cls) } Py_LOCAL(PyObject *) -_PyObject_GetState(PyObject *obj) +_PyObject_GetState(PyObject *obj, int required) { PyObject *state; PyObject *getstate; @@ -3846,6 +3846,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); @@ -3870,6 +3877,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; @@ -4099,29 +4124,24 @@ reduce_newobj(PyObject *obj, int proto) 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; @@ -4131,13 +4151,13 @@ reduce_newobj(PyObject *obj, int proto) 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; } @@ -4149,7 +4169,7 @@ reduce_newobj(PyObject *obj, int proto) Py_INCREF(v); PyTuple_SET_ITEM(newargs, i+1, v); } - Py_DECREF(args); + Py_XDECREF(args); } else if (proto >= 4) { _Py_IDENTIFIER(__newobj_ex__); @@ -4180,7 +4200,8 @@ reduce_newobj(PyObject *obj, int proto) return NULL; } - state = _PyObject_GetState(obj); + state = _PyObject_GetState(obj, + !hasargs && !PyList_Check(obj) && !PyDict_Check(obj)); if (state == NULL) { Py_DECREF(newobj); Py_DECREF(newargs); |