Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b4c98ed

Browse files
bpo-41288: Refactor of unpickling NEWOBJ and NEWOBJ_EX opcodes. (GH-21472)
* Share code for NEWOBJ and NEWOBJ_EX. * More detailed error messages.
1 parent d583738 commit b4c98ed

File tree

1 file changed

+33
-76
lines changed

1 file changed

+33
-76
lines changed

Modules/_pickle.c

Lines changed: 33 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -5912,118 +5912,75 @@ load_inst(UnpicklerObject *self)
59125912
return 0;
59135913
}
59145914

5915-
static int
5916-
load_newobj(UnpicklerObject *self)
5915+
static void
5916+
newobj_unpickling_error(const char * msg, int use_kwargs, PyObject *arg)
59175917
{
5918-
PyObject *args = NULL;
5919-
PyObject *clsraw = NULL;
5920-
PyTypeObject *cls; /* clsraw cast to its true type */
5921-
PyObject *obj;
59225918
PickleState *st = _Pickle_GetGlobalState();
5923-
5924-
/* Stack is ... cls argtuple, and we want to call
5925-
* cls.__new__(cls, *argtuple).
5926-
*/
5927-
PDATA_POP(self->stack, args);
5928-
if (args == NULL)
5929-
goto error;
5930-
if (!PyTuple_Check(args)) {
5931-
PyErr_SetString(st->UnpicklingError,
5932-
"NEWOBJ expected an arg " "tuple.");
5933-
goto error;
5934-
}
5935-
5936-
PDATA_POP(self->stack, clsraw);
5937-
cls = (PyTypeObject *)clsraw;
5938-
if (cls == NULL)
5939-
goto error;
5940-
if (!PyType_Check(cls)) {
5941-
PyErr_SetString(st->UnpicklingError, "NEWOBJ class argument "
5942-
"isn't a type object");
5943-
goto error;
5944-
}
5945-
if (cls->tp_new == NULL) {
5946-
PyErr_SetString(st->UnpicklingError, "NEWOBJ class argument "
5947-
"has NULL tp_new");
5948-
goto error;
5949-
}
5950-
5951-
/* Call __new__. */
5952-
obj = cls->tp_new(cls, args, NULL);
5953-
if (obj == NULL)
5954-
goto error;
5955-
5956-
Py_DECREF(args);
5957-
Py_DECREF(clsraw);
5958-
PDATA_PUSH(self->stack, obj, -1);
5959-
return 0;
5960-
5961-
error:
5962-
Py_XDECREF(args);
5963-
Py_XDECREF(clsraw);
5964-
return -1;
5919+
PyErr_Format(st->UnpicklingError, msg,
5920+
use_kwargs ? "NEWOBJ_EX" : "NEWOBJ",
5921+
Py_TYPE(arg)->tp_name);
59655922
}
59665923

59675924
static int
5968-
load_newobj_ex(UnpicklerObject *self)
5925+
load_newobj(UnpicklerObject *self, int use_kwargs)
59695926
{
5970-
PyObject *cls, *args, *kwargs;
5927+
PyObject *cls, *args, *kwargs = NULL;
59715928
PyObject *obj;
5972-
PickleState *st = _Pickle_GetGlobalState();
59735929

5974-
PDATA_POP(self->stack, kwargs);
5975-
if (kwargs == NULL) {
5976-
return -1;
5930+
/* Stack is ... cls args [kwargs], and we want to call
5931+
* cls.__new__(cls, *args, **kwargs).
5932+
*/
5933+
if (use_kwargs) {
5934+
PDATA_POP(self->stack, kwargs);
5935+
if (kwargs == NULL) {
5936+
return -1;
5937+
}
59775938
}
59785939
PDATA_POP(self->stack, args);
59795940
if (args == NULL) {
5980-
Py_DECREF(kwargs);
5941+
Py_XDECREF(kwargs);
59815942
return -1;
59825943
}
59835944
PDATA_POP(self->stack, cls);
59845945
if (cls == NULL) {
5985-
Py_DECREF(kwargs);
5946+
Py_XDECREF(kwargs);
59865947
Py_DECREF(args);
59875948
return -1;
59885949
}
59895950

59905951
if (!PyType_Check(cls)) {
5991-
PyErr_Format(st->UnpicklingError,
5992-
"NEWOBJ_EX class argument must be a type, not %.200s",
5993-
Py_TYPE(cls)->tp_name);
5952+
newobj_unpickling_error("%s class argument must be a type, not %.200s",
5953+
use_kwargs, cls);
59945954
goto error;
59955955
}
5996-
59975956
if (((PyTypeObject *)cls)->tp_new == NULL) {
5998-
PyErr_SetString(st->UnpicklingError,
5999-
"NEWOBJ_EX class argument doesn't have __new__");
5957+
newobj_unpickling_error("%s class argument '%.200s' doesn't have __new__",
5958+
use_kwargs, cls);
60005959
goto error;
60015960
}
60025961
if (!PyTuple_Check(args)) {
6003-
PyErr_Format(st->UnpicklingError,
6004-
"NEWOBJ_EX args argument must be a tuple, not %.200s",
6005-
Py_TYPE(args)->tp_name);
5962+
newobj_unpickling_error("%s args argument must be a tuple, not %.200s",
5963+
use_kwargs, args);
60065964
goto error;
60075965
}
6008-
if (!PyDict_Check(kwargs)) {
6009-
PyErr_Format(st->UnpicklingError,
6010-
"NEWOBJ_EX kwargs argument must be a dict, not %.200s",
6011-
Py_TYPE(kwargs)->tp_name);
5966+
if (use_kwargs && !PyDict_Check(kwargs)) {
5967+
newobj_unpickling_error("%s kwargs argument must be a dict, not %.200s",
5968+
use_kwargs, kwargs);
60125969
goto error;
60135970
}
60145971

60155972
obj = ((PyTypeObject *)cls)->tp_new((PyTypeObject *)cls, args, kwargs);
6016-
Py_DECREF(kwargs);
6017-
Py_DECREF(args);
6018-
Py_DECREF(cls);
60195973
if (obj == NULL) {
6020-
return -1;
5974+
goto error;
60215975
}
5976+
Py_XDECREF(kwargs);
5977+
Py_DECREF(args);
5978+
Py_DECREF(cls);
60225979
PDATA_PUSH(self->stack, obj, -1);
60235980
return 0;
60245981

60255982
error:
6026-
Py_DECREF(kwargs);
5983+
Py_XDECREF(kwargs);
60275984
Py_DECREF(args);
60285985
Py_DECREF(cls);
60295986
return -1;
@@ -6956,8 +6913,8 @@ load(UnpicklerObject *self)
69566913
OP(FROZENSET, load_frozenset)
69576914
OP(OBJ, load_obj)
69586915
OP(INST, load_inst)
6959-
OP(NEWOBJ, load_newobj)
6960-
OP(NEWOBJ_EX, load_newobj_ex)
6916+
OP_ARG(NEWOBJ, load_newobj, 0)
6917+
OP_ARG(NEWOBJ_EX, load_newobj, 1)
69616918
OP(GLOBAL, load_global)
69626919
OP(STACK_GLOBAL, load_stack_global)
69636920
OP(APPEND, load_append)

0 commit comments

Comments
 (0)