Skip to content

Commit a92d16a

Browse files
committed
SF patch #452239 by Gordon McMillan, to fix SF bug #451547.
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).
1 parent 9454ad7 commit a92d16a

1 file changed

Lines changed: 25 additions & 1 deletion

File tree

Modules/cPickle.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1623,7 +1623,7 @@ save_inst(Picklerobject *self, PyObject *args) {
16231623

16241624
static int
16251625
save_global(Picklerobject *self, PyObject *args, PyObject *name) {
1626-
PyObject *global_name = 0, *module = 0;
1626+
PyObject *global_name = 0, *module = 0, *mod = 0, *moddict = 0, *klass = 0;
16271627
char *name_str, *module_str;
16281628
int module_size, name_size, res = -1;
16291629

@@ -1648,6 +1648,29 @@ save_global(Picklerobject *self, PyObject *args, PyObject *name) {
16481648
module_str = PyString_AS_STRING((PyStringObject *)module);
16491649
name_str = PyString_AS_STRING((PyStringObject *)global_name);
16501650

1651+
mod = PyImport_ImportModule(module_str);
1652+
if (mod == NULL) {
1653+
/* Py_ErrClear(); ?? */
1654+
cPickle_ErrFormat(PicklingError,
1655+
"Can't pickle %s: it's not found as %s.%s",
1656+
"OSS", args, module, global_name);
1657+
goto finally;
1658+
}
1659+
moddict = PyModule_GetDict(mod); /* borrowed ref */
1660+
klass = PyDict_GetItemString(moddict, name_str); /* borrowed ref */
1661+
if (klass == NULL) {
1662+
cPickle_ErrFormat(PicklingError,
1663+
"Can't pickle %s: it's not found as %s.%s",
1664+
"OSS", args, module, global_name);
1665+
goto finally;
1666+
}
1667+
if (klass != args) {
1668+
cPickle_ErrFormat(PicklingError,
1669+
"Can't pickle %s: it's not the same object as %s.%s",
1670+
"OSS", args, module, global_name);
1671+
goto finally;
1672+
}
1673+
16511674
if ((*self->write_func)(self, &global, 1) < 0)
16521675
goto finally;
16531676

@@ -1671,6 +1694,7 @@ save_global(Picklerobject *self, PyObject *args, PyObject *name) {
16711694
finally:
16721695
Py_XDECREF(module);
16731696
Py_XDECREF(global_name);
1697+
Py_XDECREF(mod);
16741698

16751699
return res;
16761700
}

0 commit comments

Comments
 (0)