mirror of https://github.com/python/cpython
bpo-41288: Refactor of unpickling NEWOBJ and NEWOBJ_EX opcodes. (GH-21472)
* Share code for NEWOBJ and NEWOBJ_EX. * More detailed error messages.
This commit is contained in:
parent
d583738a87
commit
b4c98ed41e
|
@ -5912,118 +5912,75 @@ load_inst(UnpicklerObject *self)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
load_newobj(UnpicklerObject *self)
|
newobj_unpickling_error(const char * msg, int use_kwargs, PyObject *arg)
|
||||||
{
|
{
|
||||||
PyObject *args = NULL;
|
|
||||||
PyObject *clsraw = NULL;
|
|
||||||
PyTypeObject *cls; /* clsraw cast to its true type */
|
|
||||||
PyObject *obj;
|
|
||||||
PickleState *st = _Pickle_GetGlobalState();
|
PickleState *st = _Pickle_GetGlobalState();
|
||||||
|
PyErr_Format(st->UnpicklingError, msg,
|
||||||
/* Stack is ... cls argtuple, and we want to call
|
use_kwargs ? "NEWOBJ_EX" : "NEWOBJ",
|
||||||
* cls.__new__(cls, *argtuple).
|
Py_TYPE(arg)->tp_name);
|
||||||
*/
|
|
||||||
PDATA_POP(self->stack, args);
|
|
||||||
if (args == NULL)
|
|
||||||
goto error;
|
|
||||||
if (!PyTuple_Check(args)) {
|
|
||||||
PyErr_SetString(st->UnpicklingError,
|
|
||||||
"NEWOBJ expected an arg " "tuple.");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
PDATA_POP(self->stack, clsraw);
|
|
||||||
cls = (PyTypeObject *)clsraw;
|
|
||||||
if (cls == NULL)
|
|
||||||
goto error;
|
|
||||||
if (!PyType_Check(cls)) {
|
|
||||||
PyErr_SetString(st->UnpicklingError, "NEWOBJ class argument "
|
|
||||||
"isn't a type object");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if (cls->tp_new == NULL) {
|
|
||||||
PyErr_SetString(st->UnpicklingError, "NEWOBJ class argument "
|
|
||||||
"has NULL tp_new");
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call __new__. */
|
|
||||||
obj = cls->tp_new(cls, args, NULL);
|
|
||||||
if (obj == NULL)
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
Py_DECREF(args);
|
|
||||||
Py_DECREF(clsraw);
|
|
||||||
PDATA_PUSH(self->stack, obj, -1);
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
|
||||||
Py_XDECREF(args);
|
|
||||||
Py_XDECREF(clsraw);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
load_newobj_ex(UnpicklerObject *self)
|
load_newobj(UnpicklerObject *self, int use_kwargs)
|
||||||
{
|
{
|
||||||
PyObject *cls, *args, *kwargs;
|
PyObject *cls, *args, *kwargs = NULL;
|
||||||
PyObject *obj;
|
PyObject *obj;
|
||||||
PickleState *st = _Pickle_GetGlobalState();
|
|
||||||
|
|
||||||
PDATA_POP(self->stack, kwargs);
|
/* Stack is ... cls args [kwargs], and we want to call
|
||||||
if (kwargs == NULL) {
|
* cls.__new__(cls, *args, **kwargs).
|
||||||
return -1;
|
*/
|
||||||
|
if (use_kwargs) {
|
||||||
|
PDATA_POP(self->stack, kwargs);
|
||||||
|
if (kwargs == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PDATA_POP(self->stack, args);
|
PDATA_POP(self->stack, args);
|
||||||
if (args == NULL) {
|
if (args == NULL) {
|
||||||
Py_DECREF(kwargs);
|
Py_XDECREF(kwargs);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
PDATA_POP(self->stack, cls);
|
PDATA_POP(self->stack, cls);
|
||||||
if (cls == NULL) {
|
if (cls == NULL) {
|
||||||
Py_DECREF(kwargs);
|
Py_XDECREF(kwargs);
|
||||||
Py_DECREF(args);
|
Py_DECREF(args);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PyType_Check(cls)) {
|
if (!PyType_Check(cls)) {
|
||||||
PyErr_Format(st->UnpicklingError,
|
newobj_unpickling_error("%s class argument must be a type, not %.200s",
|
||||||
"NEWOBJ_EX class argument must be a type, not %.200s",
|
use_kwargs, cls);
|
||||||
Py_TYPE(cls)->tp_name);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((PyTypeObject *)cls)->tp_new == NULL) {
|
if (((PyTypeObject *)cls)->tp_new == NULL) {
|
||||||
PyErr_SetString(st->UnpicklingError,
|
newobj_unpickling_error("%s class argument '%.200s' doesn't have __new__",
|
||||||
"NEWOBJ_EX class argument doesn't have __new__");
|
use_kwargs, cls);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!PyTuple_Check(args)) {
|
if (!PyTuple_Check(args)) {
|
||||||
PyErr_Format(st->UnpicklingError,
|
newobj_unpickling_error("%s args argument must be a tuple, not %.200s",
|
||||||
"NEWOBJ_EX args argument must be a tuple, not %.200s",
|
use_kwargs, args);
|
||||||
Py_TYPE(args)->tp_name);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (!PyDict_Check(kwargs)) {
|
if (use_kwargs && !PyDict_Check(kwargs)) {
|
||||||
PyErr_Format(st->UnpicklingError,
|
newobj_unpickling_error("%s kwargs argument must be a dict, not %.200s",
|
||||||
"NEWOBJ_EX kwargs argument must be a dict, not %.200s",
|
use_kwargs, kwargs);
|
||||||
Py_TYPE(kwargs)->tp_name);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = ((PyTypeObject *)cls)->tp_new((PyTypeObject *)cls, args, kwargs);
|
obj = ((PyTypeObject *)cls)->tp_new((PyTypeObject *)cls, args, kwargs);
|
||||||
Py_DECREF(kwargs);
|
if (obj == NULL) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
Py_XDECREF(kwargs);
|
||||||
Py_DECREF(args);
|
Py_DECREF(args);
|
||||||
Py_DECREF(cls);
|
Py_DECREF(cls);
|
||||||
if (obj == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
PDATA_PUSH(self->stack, obj, -1);
|
PDATA_PUSH(self->stack, obj, -1);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
Py_DECREF(kwargs);
|
Py_XDECREF(kwargs);
|
||||||
Py_DECREF(args);
|
Py_DECREF(args);
|
||||||
Py_DECREF(cls);
|
Py_DECREF(cls);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -6956,8 +6913,8 @@ load(UnpicklerObject *self)
|
||||||
OP(FROZENSET, load_frozenset)
|
OP(FROZENSET, load_frozenset)
|
||||||
OP(OBJ, load_obj)
|
OP(OBJ, load_obj)
|
||||||
OP(INST, load_inst)
|
OP(INST, load_inst)
|
||||||
OP(NEWOBJ, load_newobj)
|
OP_ARG(NEWOBJ, load_newobj, 0)
|
||||||
OP(NEWOBJ_EX, load_newobj_ex)
|
OP_ARG(NEWOBJ_EX, load_newobj, 1)
|
||||||
OP(GLOBAL, load_global)
|
OP(GLOBAL, load_global)
|
||||||
OP(STACK_GLOBAL, load_stack_global)
|
OP(STACK_GLOBAL, load_stack_global)
|
||||||
OP(APPEND, load_append)
|
OP(APPEND, load_append)
|
||||||
|
|
Loading…
Reference in New Issue