New submission from kai zhu <kai...@ugcs.caltech.edu>: rather than serialize python dicts & list to json / xml / protocol buffer for web use, its more efficient to just serialize w/ repr() & then use eval(), if only there was a way to guarantee arbitrary code can't b executed.
this is a very simple proposed method for the latter. b4 eval(), it compiles string to python code object & checks for: 1. co_names list can only contain 'False', 'None', 'True' -this ensures no function call can b made 2. co_consts list cannot contain code objects -embedded lambda's r forbidden. 3. grave accents are explicitly forbidden. here is the code for both python2.5 (intended for google appengine) & python 3k: ## safe_eval.py import sys, types if sys.version_info[0] == 2: ## py2x _co_safe = 'co_argcount co_nlocals co_varnames co_filename co_freevars co_cellvars'.split(' ') else: ## py3k _co_safe = 'co_argcount co_kwonlyargcount co_nlocals co_names co_varnames co_filename co_freevars co_cellvars'.split(' ') ## safely eval string with no side-effects def safe_eval(ss): if not ss: return None if '`' in ss: raise ValueError('grave accent "`" forbidden') cc = compile(ss, '', 'eval') for aa in _co_safe: if getattr(cc, aa): raise ValueError(aa + ' must be empty / none / zero') for aa in cc.co_names: if aa not in ['False', 'None', 'True']: raise ValueError('co_names can only contain False, None, True') for aa in cc.co_consts: if isinstance(aa, types.CodeType): raise TypeError('code objects not allowed in co_consts') return eval(cc, {}) python2.5 Python 2.5.5 (r255:77872, Nov 28 2010, 19:00:19) [GCC 4.4.5] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from safe_eval import safe_eval >>> safe_eval('[False, None, True, {1:2}]') [False, None, True, {1: 2}] >>> safe_eval('[None, False, True, {1:2}, evil_code()]') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "safe_eval.py", line 19, in safe_eval if aa not in ['False', 'None', 'True']: raise ValueError('co_names can only contain False, None, True') ValueError: co_names can only contain False, None, True >>> safe_eval('[None, False, True, {1:2}, `evil_code()`]') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "safe_eval.py", line 14, in safe_eval if '`' in ss: raise ValueError('grave accent "`" forbidden') ValueError: grave accent "`" forbidden >>> safe_eval('[None, False, True, {1:2}, lambda: evil_code()]') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "safe_eval.py", line 21, in safe_eval if isinstance(aa, types.CodeType): raise TypeError('code objects not allowed in co_consts') TypeError: code objects not allowed in co_consts ---------- components: Library (Lib) messages: 126586 nosy: kaizhu priority: normal severity: normal status: open title: safely eval serialized dict/list data from arbitrary string over web with no side effects type: feature request versions: Python 2.5, Python 3.3 _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue10953> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com