-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsafe_eval.py
33 lines (32 loc) · 1.09 KB
/
safe_eval.py
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
from types import CodeType
def safe_eval_norecurse(input_string, allowed_names=None, builtins_dict=None, compiled_name="<string>"):
if allowed_names is None:
allowed_names = {}
if builtins_dict is None:
builtins_dict = {}
stack = [compile(input_string, compiled_name, "eval")]
stack_push = stack.append
stack_pop = stack.pop
indexlist = [0]
indexlist_append = indexlist.append
indexlist_pop = indexlist.pop
breakloop = False
while indexlist:
code = stack[-1]
for obj in code.co_consts[indexlist[-1]:]:
indexlist[-1] += 1
if isinstance(obj, CodeType):
indexlist_append(0)
stack_push(obj)
breakloop = True
break
if breakloop:
breakloop = False
continue
else:
indexlist_pop()
for name in code.co_names:
if name not in allowed_names:
raise NameError(f"Use of {name} not allowed")
stack_pop()
return eval(code, {"__builtins__": builtins_dict}, allowed_names)