Skip to content

Commit

Permalink
Harmonize errors raised by 'guarded_hasattr'.
Browse files Browse the repository at this point in the history
C and Python should raise the same exceptions in the same cases.

Closes #13.
  • Loading branch information
tseaver authored and hannosch committed May 2, 2017
1 parent 00dc7ca commit da8a7ea
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/AccessControl/ZopeGuards.py
Expand Up @@ -59,7 +59,7 @@ def initialize(impl):
def guarded_hasattr(object, name):
try:
guarded_getattr(object, name)
except (AttributeError, Unauthorized):
except (AttributeError, Unauthorized, TypeError):
return 0
return 1
safe_builtins['hasattr'] = guarded_hasattr
Expand Down
4 changes: 4 additions & 0 deletions src/AccessControl/cAccessControl.c
Expand Up @@ -2143,6 +2143,10 @@ guarded_getattr(PyObject *inst, PyObject *name, PyObject *default_,
Py_DECREF(v);
return NULL;
}
} else {
/* raise TypeError, name */
PyErr_SetObject(PyExc_TypeError, name);
return NULL;
}

unauth:
Expand Down
61 changes: 59 additions & 2 deletions src/AccessControl/tests/testZopeGuards.py
Expand Up @@ -88,6 +88,18 @@ def setUp(self):
def tearDown(self):
self.setSecurityManager(self.__old)

def test_miss(self):
from AccessControl.ZopeGuards import guarded_getattr
obj, name = object(), 'nonesuch'
self.assertRaises(AttributeError, guarded_getattr, obj, name)
self.assertEqual(len(self.__sm.calls), 0)

def test_unhashable_key(self):
from AccessControl.ZopeGuards import guarded_getattr
obj, name = object(), {}
self.assertRaises(TypeError, guarded_getattr, obj, name)
self.assertEqual(len(self.__sm.calls), 0)

def test_unauthorized(self):
from AccessControl import Unauthorized
from AccessControl.ZopeGuards import guarded_getattr
Expand All @@ -96,14 +108,14 @@ def test_unauthorized(self):
rc = sys.getrefcount(value)
self.__sm.reject = True
self.assertRaises(Unauthorized, guarded_getattr, obj, name)
self.assert_(self.__sm.calls)
self.assertEqual(len(self.__sm.calls), 1)
del self.__sm.calls[:]
self.assertEqual(rc, sys.getrefcount(value))

def test_calls_validate_for_unknown_type(self):
from AccessControl.ZopeGuards import guarded_getattr
guarded_getattr(self, 'test_calls_validate_for_unknown_type')
self.assert_(self.__sm.calls)
self.assertEqual(len(self.__sm.calls), 1)

def test_attr_handler_table(self):
from AccessControl import Unauthorized
Expand All @@ -128,6 +140,50 @@ def test_attr_handler_table(self):
ContainerAssertions[_dict] = old


class TestGuardedHasattr(GuardTestCase):

def setUp(self):
self.__sm = SecurityManager()
self.__old = self.setSecurityManager(self.__sm)

def tearDown(self):
self.setSecurityManager(self.__old)

def test_miss(self):
from AccessControl.ZopeGuards import guarded_hasattr
obj, name = object(), 'nonesuch'
self.assertFalse(guarded_hasattr(obj, name))
self.assertEqual(len(self.__sm.calls), 0)
del self.__sm.calls[:]

def test_unhashable_key(self):
from AccessControl.ZopeGuards import guarded_hasattr
obj, name = object(), {}
self.assertFalse(guarded_hasattr(obj, name))
self.assertEqual(len(self.__sm.calls), 0)

def test_unauthorized(self):
from AccessControl.ZopeGuards import guarded_hasattr
obj, name = Method(), 'args'
value = getattr(obj, name)
rc = sys.getrefcount(value)
self.__sm.reject = True
self.assertFalse(guarded_hasattr(obj, name))
self.assertEqual(len(self.__sm.calls), 1)
del self.__sm.calls[:]
self.assertEqual(rc, sys.getrefcount(value))

def test_hit(self):
from AccessControl.ZopeGuards import guarded_hasattr
obj, name = Method(), 'args'
value = getattr(obj, name)
rc = sys.getrefcount(value)
self.assertTrue(guarded_hasattr(obj, name))
self.assertEqual(len(self.__sm.calls), 1)
del self.__sm.calls[:]
self.assertEqual(rc, sys.getrefcount(value))


class TestDictGuards(GuardTestCase):

def test_get_simple(self):
Expand Down Expand Up @@ -865,6 +921,7 @@ def test_suite():
doctest.DocTestSuite(),
])
for cls in (TestGuardedGetattr,
TestGuardedHasattr,
TestDictGuards,
TestBuiltinFunctionGuards,
TestListGuards,
Expand Down

0 comments on commit da8a7ea

Please sign in to comment.