2012-05-18 15 views
7

私はこの質問が以前に尋ねられていることを認識していますが、このケースは少し異なります。Python Webサーバーで数学的なユーザーコードを実行すると、最も簡単な方法は何ですか?

web.pyを使用して)Pythonイメージボードを実行して、コードを送信して新しいイメージを生成できるようにします。コードはR、G、B値、例えばX、ピクセルのy座標を取得し、返す単一の関数の形であろう。のみ

def simpleGradient(xrel,yrel): 
    r = xrel*256 
    g = yrel*256 
    b = 0 
    return [r,g,b] 

微小構文が必要であるが、それ必ずしもPythonである必要はありません。限られた範囲のexecを使用することはあまりにも安全ではないように思えますし、PyPyやVMを使用することは不必要に複雑に思えます(私はこれに全く新しいです)。

これをサンドボックス化するのではなく、はるかに小さな言語でコードを実行するためのpythonの方法がありますか? Pythonのサブセット(解析とホワイトリスト?)、または埋め込むことができる数学指向の言語ですか?

+2

私は実際にはPyPyサンドボックスを使用します。 –

+0

私はそれに反対していくつかの他の答えを読んだ...だから私は実際にPyPyを見ていない - 私はそれをチェックしますよ – SudoNhim

+0

素晴らしい質問、多分PyPyは答えです。今日、Pythonがルアと比べるとちょっと短いかもしれないことについて話していただけです。 –

答えて

2

これは私が行った解決策です。このアプローチのセキュリティの議論については、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 

これは、コードの数学的な部分のみを受け入れるように設計されていることに注意してください。関数定義とreturn文が用意されています。

必要なすべての安全な構造をホワイトリストに登録し、特に安全な構造を必要とするホワイトリストを作成するこの方法は、Pythonの多くの有用なサブセットを生成するように変更できます。ユーザーのスクリプトに最適!

これが安全に実行されるためには、ユーザーコードが無限ループまたは同様のものを生成した場合に、名前の衝突を減らしタイムアウトするためにタイムアウト付きのスレッドが必要です。

+0

これはスタンドアロンの質問IMOである必要があります。 – TryPyPy

+0

申し訳ありません。私はうまくいけばそれをチェックできる人を知っている。彼がそれを見つけたら、私はそれをもっと答えのように再フォーマットします。 (それ以外は削除します)。 – SudoNhim

+0

私が意味していたのは、この答えを新しい質問に変換すればもっと目を(そしておそらく新しい提案を)得るでしょう:) – TryPyPy

関連する問題