Log message for revision 29837:
  merged fix from tseaver-collector_1460 branch

Changed:
  U   Zope/trunk/doc/CHANGES.txt
  U   Zope/trunk/lib/python/AccessControl/ZopeGuards.py
  U   Zope/trunk/lib/python/AccessControl/tests/testZopeGuards.py

-=-
Modified: Zope/trunk/doc/CHANGES.txt
===================================================================
--- Zope/trunk/doc/CHANGES.txt  2005-04-02 09:08:42 UTC (rev 29836)
+++ Zope/trunk/doc/CHANGES.txt  2005-04-02 09:11:40 UTC (rev 29837)
@@ -72,6 +72,8 @@
 
     Bugs fixed
 
+      - Collector #1460: guarded_apply was too restrictive.
+
       - OFS.Traversable still used a string 'NotFound' exception.
 
       - ZPublisher would fail to recognize a XML-RPC request if the

Modified: Zope/trunk/lib/python/AccessControl/ZopeGuards.py
===================================================================
--- Zope/trunk/lib/python/AccessControl/ZopeGuards.py   2005-04-02 09:08:42 UTC 
(rev 29836)
+++ Zope/trunk/lib/python/AccessControl/ZopeGuards.py   2005-04-02 09:11:40 UTC 
(rev 29837)
@@ -155,17 +155,44 @@
 # See comment in SimpleObjectPolicies for an explanation of what the
 # dicts below actually mean.
 
-ContainerAssertions[type({})] = {
+_dict_white_list = {
     'clear':1, 'copy':1, 'fromkeys':1, 'get':get_dict_get, 'has_key':1,
     'items':1, 'iteritems':1, 'keys':1,
     'iterkeys': get_iter,  'itervalues':get_iter,
     'pop':get_dict_pop, 'popitem':1, 'setdefault':1, 'update':1, 'values':1}
 
-ContainerAssertions[type([])] = {
+def _check_dict_access(name, value):
+    # Check whether value is a dict method
+    self = getattr(value, '__self__', None)
+    if self is None: # item
+        return 1
+    # Disallow spoofing
+    if type(self) is not dict:
+        return 0
+    if getattr(value, '__name__', None) != name:
+        return 0
+    return _dict_white_list.get(name, 0)
+
+ContainerAssertions[type({})] = _check_dict_access
+
+_list_white_list = {
     'append':1, 'count':1, 'extend':1, 'index':1, 'insert':1,
     'pop':get_list_pop, 'remove':1, 'reverse':1, 'sort':1}
 
+def _check_list_access(name, value):
+    # Check whether value is a dict method
+    self = getattr(value, '__self__', None)
+    if self is None: # item
+        return 1
+    # Disallow spoofing
+    if type(self) is not list:
+        return 0
+    if getattr(value, '__name__', None) != name:
+        return 0
+    return _list_white_list.get(name, 0)
 
+ContainerAssertions[type([])] = _check_list_access
+
 # This implementation of a "safe" iterator uses a global guard()
 # function to implement the actual guard.  This check is defined as a
 # global so that it can delay imports of some module to avoid circular

Modified: Zope/trunk/lib/python/AccessControl/tests/testZopeGuards.py
===================================================================
--- Zope/trunk/lib/python/AccessControl/tests/testZopeGuards.py 2005-04-02 
09:08:42 UTC (rev 29836)
+++ Zope/trunk/lib/python/AccessControl/tests/testZopeGuards.py 2005-04-02 
09:11:40 UTC (rev 29837)
@@ -404,6 +404,44 @@
             untouched.sort()
             self.fail("Unexercised wrappers: %r" % untouched)
 
+    def test_dict_access(self):
+        from RestrictedPython.tests import verify
+
+        SIMPLE_DICT_ACCESS_SCRIPT = """
+def foo(text):
+    return text
+
+kw = {'text':'baz'}
+print foo(**kw)
+
+kw = {'text':True}
+print foo(**kw)
+"""
+        code, its_globals = self._compile_str(SIMPLE_DICT_ACCESS_SCRIPT, 'x')
+        verify.verify(code)
+
+        sm = SecurityManager()
+        old = self.setSecurityManager(sm)
+        try:
+            exec code in its_globals
+        finally:
+            self.setSecurityManager(old)
+
+        self.assertEqual(its_globals['_print'](),
+                        'baz\nTrue\n')
+        
+    def _compile_str(self, text, name):
+        from RestrictedPython import compile_restricted
+        from AccessControl.ZopeGuards import get_safe_globals, guarded_getattr
+
+        code = compile_restricted(text, name, 'exec')
+
+        g = get_safe_globals()
+        g['_getattr_'] = guarded_getattr
+        g['__debug__'] = 1  # so assert statements are active
+        g['__name__'] = __name__ # so classes can be defined in the script
+        return code, g
+
     # Compile code in fname, as restricted Python.  Return the
     # compiled code, and a safe globals dict for running it in.
     # fname is the string name of a Python file; it must be found
@@ -413,14 +451,9 @@
         from AccessControl.ZopeGuards import get_safe_globals, guarded_getattr
 
         fn = os.path.join( _HERE, fname)
-        code = compile_restricted(open(fn).read(), fn, 'exec')
+        text = open(fn).read()
+        return self._compile_str(text, fn)
 
-        g = get_safe_globals()
-        g['_getattr_'] = guarded_getattr
-        g['__debug__'] = 1  # so assert statements are active
-        g['__name__'] = __name__ # so classes can be defined in the script
-        return code, g
-
     # d is a dict, the globals for execution or our safe builtins.
     # The callable values which aren't the same as the corresponding
     # entries in __builtin__ are wrapped in a FuncWrapper, so we can

_______________________________________________
Zope-Checkins maillist  -  Zope-Checkins@zope.org
http://mail.zope.org/mailman/listinfo/zope-checkins

Reply via email to