From 9a59d0955603b2d439f0bec662c31a0e2a7401ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Thu, 17 Dec 2009 11:27:24 +0100 Subject: [PATCH] Add cache to safe_eval --- CHANGELOG | 1 + trytond/tools/misc.py | 44 +++++++++++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 2632138dba..8bf4061302 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Add cache to safe_eval * Rename HttpDaemon into XMLRPCDaemon * Improve TranslateFactory to fetch all translations for a report in one query * Handle displayname on webdav.collection diff --git a/trytond/tools/misc.py b/trytond/tools/misc.py index 815358477e..d35da9286a 100644 --- a/trytond/tools/misc.py +++ b/trytond/tools/misc.py @@ -20,6 +20,11 @@ except ImportError: import StringIO import dis import datetime +try: + import hashlib +except ImportError: + hashlib = None + import md5 def find_in_path(name): if os.name == "nt": @@ -510,23 +515,34 @@ _ALLOWED_CODES = set(dis.opmap[x] for x in [ ] if x in dis.opmap) +_SAFE_EVAL_CACHE = {} + def safe_eval(source, data=None): if '__subclasses__' in source: raise ValueError('__subclasses__ not allowed') - c = compile(source, '', 'eval') - codes = [] - s = c.co_code - i = 0 - while i < len(s): - code = ord(s[i]) - codes.append(code) - if code >= dis.HAVE_ARGUMENT: - i += 3 - else: - i += 1 - for code in codes: - if code not in _ALLOWED_CODES: - raise ValueError('opcode %s not allowed' % dis.opname[code]) + if hashlib: + key = hashlib.md5(source).digest() + else: + key = md5.new(source).digest() + c = _SAFE_EVAL_CACHE.get(key) + if not c: + c = compile(source, '', 'eval') + codes = [] + s = c.co_code + i = 0 + while i < len(s): + code = ord(s[i]) + codes.append(code) + if code >= dis.HAVE_ARGUMENT: + i += 3 + else: + i += 1 + for code in codes: + if code not in _ALLOWED_CODES: + raise ValueError('opcode %s not allowed' % dis.opname[code]) + if len(_SAFE_EVAL_CACHE) > 1024: + _SAFE_EVAL_CACHE.clear() + _SAFE_EVAL_CACHE[key] = c return eval(c, {'__builtins__': { 'True': True, 'False': False,