這是我一起去的解決方案。對於這種方法的安全性的討論,請參見
感謝arifwn,我進入探索Python的ast
(抽象語法樹)模塊。該模塊提供用於遍歷樹的類ast.NodeVisitor
。此代碼的子類NodeVisitor
創建一個語法檢查器,將基本數學所需的代碼列入白名單。函數調用和名稱是專門監控的,因爲只有某些函數應該被允許,並且只允許使用未使用的名稱。
import ast
allowed_functions = set([
#math library
'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh',
'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf',
'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod',
'frexp', 'fsum', 'gamma', 'hypot', 'isinf', 'isnan', 'ldexp',
'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians',
'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc',
#builtins
'abs', 'max', 'min', 'range', 'xrange'
])
allowed_node_types = set([
#Meta
'Module', 'Assign', 'Expr',
#Control
'For', 'If', 'Else',
#Data
'Store', 'Load', 'AugAssign', 'Subscript',
#Datatypes
'Num', 'Tuple', 'List',
#Operations
'BinOp', 'Add', 'Sub', 'Mult', 'Div', 'Mod', 'Compare'
])
safe_names = set([
'True', 'False', 'None'
])
class SyntaxChecker(ast.NodeVisitor):
def check(self, syntax):
tree = ast.parse(syntax)
self.passed=True
self.visit(tree)
def visit_Call(self, node):
if node.func.id not in allowed_functions:
raise SyntaxError("%s is not an allowed function!"%node.func.id)
else:
ast.NodeVisitor.generic_visit(self, node)
def visit_Name(self, node):
try:
eval(node.id)
except NameError:
ast.NodeVisitor.generic_visit(self, node)
else:
if node.id not in safe_names and node.id not in allowed_functions:
raise SyntaxError("%s is a reserved name!"%node.id)
else:
ast.NodeVisitor.generic_visit(self, node)
def generic_visit(self, node):
if type(node).__name__ not in allowed_node_types:
raise SyntaxError("%s is not allowed!"%type(node).__name__)
else:
ast.NodeVisitor.generic_visit(self, node)
if __name__ == '__main__':
x = SyntaxChecker()
while True:
try:
x.check(raw_input())
except Exception as e:
print e
請注意,這被設計爲只接受代碼的數學部分,函數定義和返回語句提供。
這種將所有必需的安全結構白名單列入白名單所需的不安全結構的方法可以修改,以產生許多有用的Python子集;非常適合用戶腳本!
請注意,爲了安全地執行此操作,它應該在它自己的線程中超時,以減少名稱衝突並在用戶代碼生成無限循環或類似代碼時超時。
我實際上會使用PyPy沙箱。 –
我讀過的其他幾個答案反對它......所以我沒有真正看過PyPy - 我會檢查出來的,謝謝 – SudoNhim
好的問題,也許PyPy是答案。今天只是在談論有關Python如何可能在這裏短缺,相比之下,說lua。 –