From 901a2256190e424b8a2da1e18be32111f37a8d91 Mon Sep 17 00:00:00 2001 From: Jeremy Fincher Date: Fri, 7 Nov 2003 19:40:03 +0000 Subject: [PATCH] Added safeEval. --- src/utils.py | 42 +++++++++++++++++++++++++++++++++++++++--- test/test_utils.py | 8 ++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/utils.py b/src/utils.py index cc1eb9790..2f3238133 100755 --- a/src/utils.py +++ b/src/utils.py @@ -43,6 +43,7 @@ import md5 import sha import string import sgmllib +import compiler import textwrap import htmlentitydefs @@ -408,12 +409,47 @@ def flatten(seq, strings=False): def saltHash(password, salt=None, hash='sha'): if salt is None: salt = mktemp()[:8] - if hash == 'md5': - hasher = md5.md5 - elif hash == 'sha': + if hash == 'sha': hasher = sha.sha + elif hash == 'md5': + hasher = md5.md5 return '|'.join([salt, hasher(salt + password).hexdigest()]) +def safeEval(s, namespace={'True': True, 'False': False, 'None': None}): + """Evaluates s, safely. Useful for turning strings into tuples/lists/etc. + without unsafely using eval().""" + node = compiler.parse(s) + nodes = compiler.parse(s).node.nodes + if not nodes: + if node.__class__ is compiler.ast.Module: + return node.doc + else: + raise ValueError, 'Unsafe string.' + node = nodes[0] + if node.__class__ is not compiler.ast.Discard: + raise ValueError, 'Invalid expression: %s' + node = node.getChildNodes()[0] + def checkNode(node): + if node.__class__ is compiler.ast.Const: + return True + if node.__class__ in (compiler.ast.List, + compiler.ast.Tuple, + compiler.ast.Dict): + return all(checkNode, node.getChildNodes()) + if node.__class__ is compiler.ast.Name: + if node.name in namespace: + return True + else: + return False + else: + return False + if checkNode(node): + return eval(s, namespace, namespace) + else: + raise ValueError, 'Unsafe string.' + + + class IterableMap(object): """Define .iteritems() in a class and subclass this to get the other iters. """ diff --git a/test/test_utils.py b/test/test_utils.py index aca43ae69..ac2bf9227 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -280,6 +280,14 @@ class UtilsTest(unittest.TestCase): (salt, hash) = s.split('|') self.assertEqual(utils.saltHash('jemfinch', salt=salt), s) + def testSafeEval(self): + for s in ['1', '()', '(1,)', '[]', '{}', '{1:2}', '{1:(2,3)}', + '1.0', '[1,2,3]', 'True', 'False', 'None', + '(True,False,None)', '"foo"', '{"foo": "bar"}']: + self.assertEqual(eval(s), utils.safeEval(s)) + for s in ['lambda: 2', 'import foo', 'foo.bar']: + self.assertRaises(ValueError, utils.safeEval, s) +