diff --git a/CHANGES.rst b/CHANGES.rst index a0e2b06289..92a1b7e790 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,6 +9,10 @@ https://github.com/zopefoundation/Zope/blob/4.x/CHANGES.rst 5.0a1 (unreleased) ------------------ +- The method ``unrestrictedTraverse`` raises an error when + the argument ``path`` is not something it can work with + (`#674 `_) + - Improve ZMI Security Tab usability for high numbers of roles (`#730 `_) diff --git a/src/OFS/Traversable.py b/src/OFS/Traversable.py index 4b940c3c48..ea13a2572f 100644 --- a/src/OFS/Traversable.py +++ b/src/OFS/Traversable.py @@ -172,10 +172,14 @@ def unrestrictedTraverse(self, path, default=_marker, restricted=False): return self if isinstance(path, str): - # Only native strings are allowed path = path.split('/') else: path = list(path) + for part in path: + if not isinstance(part, str): + raise TypeError( + "path should be a string or an iterable of strings" + ) REQUEST = {'TraversalRequestNameStack': path} path.reverse() diff --git a/src/OFS/tests/testTraverse.py b/src/OFS/tests/testTraverse.py index e387d63dd1..ee316aaa9f 100644 --- a/src/OFS/tests/testTraverse.py +++ b/src/OFS/tests/testTraverse.py @@ -425,6 +425,24 @@ def testTraverseToNameStartingWithPlus(self): self.assertTrue( self.folder1.unrestrictedTraverse('+something') == 'plus') + def testTraverseWrongType(self): + with self.assertRaises(TypeError): + self.folder1.unrestrictedTraverse(1) + with self.assertRaises(TypeError): + self.folder1.unrestrictedTraverse(b"foo") + with self.assertRaises(TypeError): + self.folder1.unrestrictedTraverse(["foo", b"bar"]) + with self.assertRaises(TypeError): + self.folder1.unrestrictedTraverse(("foo", None)) + with self.assertRaises(TypeError): + self.folder1.unrestrictedTraverse({1, "foo"}) + + def testTraverseEmptyPath(self): + self.assertEqual(self.folder1.unrestrictedTraverse(None), self.folder1) + self.assertEqual(self.folder1.unrestrictedTraverse(""), self.folder1) + self.assertEqual(self.folder1.unrestrictedTraverse([]), self.folder1) + self.assertEqual(self.folder1.unrestrictedTraverse({}), self.folder1) + class SimpleClass(object): """Class with no __bobo_traverse__."""