/usr/share/pyshared/RestrictedPython/Eval.py is in python-restrictedpython 3.6.0-0ubuntu4.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | ##############################################################################
#
# Copyright (c) 2002 Zope Foundation and Contributors.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Restricted Python Expressions
"""
__version__='$Revision: 1.6 $'[11:-2]
from RestrictedPython import compile_restricted_eval
from string import translate, strip
import string
nltosp = string.maketrans('\r\n',' ')
default_guarded_getattr = getattr # No restrictions.
def default_guarded_getitem(ob, index):
# No restrictions.
return ob[index]
PROFILE = 0
class RestrictionCapableEval:
"""A base class for restricted code."""
globals = {'__builtins__': None}
rcode = None # restricted
ucode = None # unrestricted
used = None
def __init__(self, expr):
"""Create a restricted expression
where:
expr -- a string containing the expression to be evaluated.
"""
expr = strip(expr)
self.__name__ = expr
expr = translate(expr, nltosp)
self.expr = expr
self.prepUnrestrictedCode() # Catch syntax errors.
def prepRestrictedCode(self):
if self.rcode is None:
if PROFILE:
from time import clock
start = clock()
co, err, warn, used = compile_restricted_eval(
self.expr, '<string>')
if PROFILE:
end = clock()
print 'prepRestrictedCode: %d ms for %s' % (
(end - start) * 1000, `self.expr`)
if err:
raise SyntaxError, err[0]
self.used = tuple(used.keys())
self.rcode = co
def prepUnrestrictedCode(self):
if self.ucode is None:
# Use the standard compiler.
co = compile(self.expr, '<string>', 'eval')
if self.used is None:
# Examine the code object, discovering which names
# the expression needs.
names=list(co.co_names)
used={}
i=0
code=co.co_code
l=len(code)
LOAD_NAME=101
HAVE_ARGUMENT=90
while(i < l):
c=ord(code[i])
if c==LOAD_NAME:
name=names[ord(code[i+1])+256*ord(code[i+2])]
used[name]=1
i=i+3
elif c >= HAVE_ARGUMENT: i=i+3
else: i=i+1
self.used=tuple(used.keys())
self.ucode=co
def eval(self, mapping):
# This default implementation is probably not very useful. :-(
# This is meant to be overridden.
self.prepRestrictedCode()
code = self.rcode
d = {'_getattr_': default_guarded_getattr,
'_getitem_': default_guarded_getitem}
d.update(self.globals)
has_key = d.has_key
for name in self.used:
try:
if not has_key(name):
d[name] = mapping[name]
except KeyError:
# Swallow KeyErrors since the expression
# might not actually need the name. If it
# does need the name, a NameError will occur.
pass
return eval(code, d)
def __call__(self, **kw):
return self.eval(kw)
|