diff options
-rw-r--r-- | Modules/cPickle.c | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/Modules/cPickle.c b/Modules/cPickle.c index 17da7d7917..6601290f4c 100644 --- a/Modules/cPickle.c +++ b/Modules/cPickle.c @@ -3698,6 +3698,53 @@ load_inst(Unpicklerobject *self) return 0; } +static int +load_newobj(Unpicklerobject *self) +{ + PyObject *args = NULL; + PyObject *clsraw = NULL; + PyTypeObject *cls; /* clsraw cast to its true type */ + PyObject *obj; + + /* Stack is ... cls argtuple, and we want to call + * cls.__new__(cls, *argtuple). + */ + PDATA_POP(self->stack, args); + if (args == NULL) goto Fail; + if (! PyTuple_Check(args)) { + PyErr_SetString(UnpicklingError, "NEWOBJ expected an arg " + "tuple."); + goto Fail; + } + + PDATA_POP(self->stack, clsraw); + cls = (PyTypeObject *)clsraw; + if (cls == NULL) goto Fail; + if (! PyType_Check(cls)) { + PyErr_SetString(UnpicklingError, "NEWOBJ class argument " + "isn't a type object"); + goto Fail; + } + if (cls->tp_new == NULL) { + PyErr_SetString(UnpicklingError, "NEWOBJ class argument " + "has NULL tp_new"); + goto Fail; + } + + /* Call __new__. */ + obj = cls->tp_new(cls, args, NULL); + if (obj == NULL) goto Fail; + + Py_DECREF(args); + Py_DECREF(clsraw); + PDATA_PUSH(self->stack, obj, -1); + return 0; + + Fail: + Py_XDECREF(args); + Py_XDECREF(clsraw); + return -1; +} static int load_global(Unpicklerobject *self) @@ -4461,6 +4508,11 @@ load(Unpicklerobject *self) break; continue; + case NEWOBJ: + if (load_newobj(self) < 0) + break; + continue; + case GLOBAL: if (load_global(self) < 0) break; @@ -4638,11 +4690,28 @@ noload_inst(Unpicklerobject *self) Pdata_clear(self->stack, i); if (self->readline_func(self, &s) < 0) return -1; if (self->readline_func(self, &s) < 0) return -1; - PDATA_APPEND(self->stack, Py_None,-1); + PDATA_APPEND(self->stack, Py_None, -1); return 0; } static int +noload_newobj(Unpicklerobject *self) +{ + PyObject *obj; + + PDATA_POP(self->stack, obj); /* pop argtuple */ + if (obj == NULL) return -1; + Py_DECREF(obj); + + PDATA_POP(self->stack, obj); /* pop cls */ + if (obj == NULL) return -1; + Py_DECREF(obj); + + PDATA_APPEND(self->stack, Py_None, -1); + return 0; +} + +static int noload_global(Unpicklerobject *self) { char *s; @@ -4829,6 +4898,11 @@ noload(Unpicklerobject *self) break; continue; + case NEWOBJ: + if (noload_newobj(self) < 0) + break; + continue; + case GLOBAL: if (noload_global(self) < 0) break; |