SF patch #452239 by Gordon McMillan, to fix SF bug #451547.
authorGuido van Rossum <guido@python.org>
Sat, 18 Aug 2001 21:22:07 +0000 (21:22 +0000)
committerGuido van Rossum <guido@python.org>
Sat, 18 Aug 2001 21:22:07 +0000 (21:22 +0000)
   This patch attempts to do to cPickle what Guido did
   for pickle.py v 1.50. That is: save_global tries
   importing the module, and fetching the name from the
   module. If that fails, or the returned object is not
   the same one we started with, it raises a
   PicklingError. (All this so pickling a lambda will
   fail at save time, rather than load time).

Modules/cPickle.c

index bb0d281f0fe6d013a7c2f2630bfc03a6f380ba15..2b058ef446385676ca3dc36b0b616e352ce2497f 100644 (file)
@@ -1623,7 +1623,7 @@ finally:
 
 static int
 save_global(Picklerobject *self, PyObject *args, PyObject *name) {
-    PyObject *global_name = 0, *module = 0;
+    PyObject *global_name = 0, *module = 0, *mod = 0, *moddict = 0, *klass = 0;
     char *name_str, *module_str;
     int module_size, name_size, res = -1;
 
@@ -1648,6 +1648,29 @@ save_global(Picklerobject *self, PyObject *args, PyObject *name) {
     module_str = PyString_AS_STRING((PyStringObject *)module);
     name_str   = PyString_AS_STRING((PyStringObject *)global_name);
 
+    mod = PyImport_ImportModule(module_str);
+    if (mod == NULL) {
+        /* Py_ErrClear(); ?? */
+        cPickle_ErrFormat(PicklingError,
+                         "Can't pickle %s: it's not found as %s.%s",
+                         "OSS", args, module, global_name);
+       goto finally;
+    }
+    moddict = PyModule_GetDict(mod);        /* borrowed ref */
+    klass = PyDict_GetItemString(moddict, name_str);        /* borrowed ref */
+    if (klass == NULL) {
+       cPickle_ErrFormat(PicklingError,
+                         "Can't pickle %s: it's not found as %s.%s",
+                         "OSS", args, module, global_name);
+       goto finally;
+    }
+    if (klass != args) {
+       cPickle_ErrFormat(PicklingError,
+                         "Can't pickle %s: it's not the same object as %s.%s",
+                         "OSS", args, module, global_name);
+       goto finally;
+    }
+
     if ((*self->write_func)(self, &global, 1) < 0)
         goto finally;
 
@@ -1671,6 +1694,7 @@ save_global(Picklerobject *self, PyObject *args, PyObject *name) {
 finally:
     Py_XDECREF(module);
     Py_XDECREF(global_name);
+    Py_XDECREF(mod);
 
     return res;
 }