From eab7db3ceed31404134317b4770aaf154785e600 Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Thu, 13 Feb 2003 18:24:14 +0000 Subject: [PATCH] Taught cPickle how to read pickles containing NEWOBJ. This won't get exercised by the test suite before cPickle knows how to create NEWOBJ too. For now, it was just tried once by hand (via loading a NEWOBJ pickle created by pickle.py). --- Modules/cPickle.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) 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,10 +4690,27 @@ 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) { @@ -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; -- 2.40.0