summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarius Gedminas <marius@gedmin.as>2014-01-08 16:01:15 +0200
committerMarius Gedminas <marius@gedmin.as>2014-01-08 16:01:15 +0200
commitdceaae23490a5cb2c305246305e6b3a51c29d3a5 (patch)
treecc98e5741acd7d900f4f50ab5265bd73e8bc4d31
parentd7b1b26d8034daaad051225c5470c1b134677d0d (diff)
downloadzope-security-dceaae23490a5cb2c305246305e6b3a51c29d3a5.tar.gz
Allow public access to CheckerPublic.__module__
Story time: when you pickle an object (call it obj) with a custom __reduce__ method that returns a string, the pickle module assumes this is a global and wants to know which module it came from. It obviously tries obj.__module__ first, but if that raises AttributeError, it has this insane fallback loop where it iterates over sys.modules.items() and for each module (excepting only __main__) checks if getattr(module, obj.__name__, None) is obj. Before my change if you tried >>> from zope.security.checker import CheckerPublic >>> CheckerPublic.__module__ you'd get ForbiddenAttribute: ('__module__', Global(CheckerPublic,zope.security.checker)) Until now it was just a silly inefficiency. But then six 1.5.0 was released with an interesting change: https://bitbucket.org/gutworth/six/commits/fc2decf405ea6bcd3226bb1b77069d2a2279e0b7 Now six puts these six.MovedModule() wrappers into sys.modules. When you try to access their attributes, the wrappers try to import random modules, including those that may not exist in your Python (_winreg on Linux? _tkinter also is often split off into a separate OS package). Boom: running zope.security's tests now fails in random ways: https://bitbucket.org/gutworth/six/issue/54/dependency-on-optional-tkinter-gdbm So let's make sure pickle doesn't need to iterate through sys.modules.items() and avoid the issue, m'kay?
-rw-r--r--src/zope/security/checker.py1
1 files changed, 1 insertions, 0 deletions
diff --git a/src/zope/security/checker.py b/src/zope/security/checker.py
index 8f3cfb4..e3b914d 100644
--- a/src/zope/security/checker.py
+++ b/src/zope/security/checker.py
@@ -304,6 +304,7 @@ CP_HACK_XXX = CheckerPublic
d={}
CheckerPublic = Proxy(CheckerPublic, Checker(d)) # XXX uses CheckerPy
d['__reduce__'] = CheckerPublic
+d['__module__'] = CheckerPublic
del d
# TODO: It's a bit scary above that we can pickle a proxy if access is