diff options
author | Marius Gedminas <marius@gedmin.as> | 2014-01-08 16:01:15 +0200 |
---|---|---|
committer | Marius Gedminas <marius@gedmin.as> | 2014-01-08 16:01:15 +0200 |
commit | dceaae23490a5cb2c305246305e6b3a51c29d3a5 (patch) | |
tree | cc98e5741acd7d900f4f50ab5265bd73e8bc4d31 | |
parent | d7b1b26d8034daaad051225c5470c1b134677d0d (diff) | |
download | zope-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.py | 1 |
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 |