summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2003-02-13 18:24:14 (GMT)
committerTim Peters <tim.peters@gmail.com>2003-02-13 18:24:14 (GMT)
commiteab7db3ceed31404134317b4770aaf154785e600 (patch)
tree254813ef6f509b8f8bcf92d8c1d302cd71069c49
parent7585229bbfb185c26851a600e43140e7fd28f12b (diff)
downloadcpython-eab7db3ceed31404134317b4770aaf154785e600.zip
cpython-eab7db3ceed31404134317b4770aaf154785e600.tar.gz
cpython-eab7db3ceed31404134317b4770aaf154785e600.tar.bz2
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).
-rw-r--r--Modules/cPickle.c76
1 files changed, 75 insertions, 1 deletions
diff --git a/Modules/cPickle.c b/Modules/cPickle.c
index 17da7d7..6601290 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;