2016-12-05 6 views
2

いくつかのデータを計算するアプリケーションを構築する必要があります。私は科学者がどのような計算を求められるのか分かりません。算術計算をどのように評価するのですか?

例えば、Aは、(A + 5)を計算することになるでしょう ユーザー* 3 ユーザBは、(A + 14)を計算することになるでしょう²* PI

算術演算式は科学者によって定義され、中に格納されています管理者別にデータベース。

簡単な方法を行うことです。

  1. 行うには:

    <?php 
    
        //Formula is initialized by a query in database 
        $formula= '(A + 3) * 5'; 
        //$ value is an integer entered by UserA and verify by Controller 
        $value = 42; 
    
        $arithmetic = str_replace('A', $formula, $value); 
    
        $result = eval($arithmetic); 
    

    しかし、それはこのanswer

    に@thplによって説明されるようevalは悪である私は2つのオプションがあります数式の各文字を分析して変換し、 は素晴らしい計算クラスを作成します。 (良い(確保?)正規表現で$formulaを点検し、悪eval関数を呼び出す。

  • などなど +の各側のオペランドを見つけ、additionメソッドの呼び出しによって+文字を置き換えます。

    最初のソリューションは、より多くの確保が、開発は非常に長いようで

    第二の溶液のために、私は、PHPのドキュメントでこれを見つけた:

    <?php 
        $test = '2+3*pi'; 
    
        // Remove whitespaces 
        $test = preg_replace('/\s+/', '', $test); 
    
        $number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number 
        $functions = '(?:sinh?|cosh?|tanh?|abs|acosh?|asinh?|atanh?|exp|log10|deg2rad|rad2deg|sqrt|ceil|floor|round)'; // Allowed PHP functions 
        $operators = '[+\/*\^%-]'; // Allowed math operators 
        $regexp = '/^((' . $number . '|' . $functions . '\s*\((?1)+\)|\((?1)+\))(?:' . $operators . '(?2))?)+$/'; // Final regexp, heavily using recursive patterns 
    
        if (preg_match($regexp, $q)) { 
         $test = preg_replace('!pi|π!', 'pi()', $test); // Replace pi with pi function 
         eval('$result = ' . $test . ';'); 
        } else { 
         $result = false; 
        } 
    

    最初の質問:2番目の解決策は十分安全ですか?

    私はインターネットで(もちろん)検索しましたが、最良の解決策は前のコードです。いくつかのPHP関数、真珠やPECLライブラリが私を助けることがありますか? arithmetic_eval機能?

    (私の質問は唯一のPHPに関するので、私はSecurity.SEに聞かないでください)

  • 答えて

    1

    第一溶液(カスタムパーサー)私は非常に複雑で、エラーが発生しやすくなると思うだろう。その中で最も高いリスクは、攻撃者が任意のコードを実行できるようにするバグです。多分あなたはそれを正しくすることができますが、間違いを犯すのは簡単です。

    第2の解決策(提案された正規表現ベースの検証)は良いかどうかは分かりません。 PHPの構文を分析し、質問の正規表現と比較し、文や表現を書くためにPHPにどのような微妙な方法があるかを見てみましょう。一見すると、壊滅的ではない分析のなしで安全だと言うことができるでしょう。それまでそれを使用することは非常に危険です。

    あなたはこれらの数式が管理者によって保存されると言っているので、これらのいずれかのリスクを受け入れることにします。管理者は、数式がコードを含まない真の数式であるかどうかを確認できます。信頼できる管理者が実際に使用されて評価される前にすべてをレビューすれば、数式のようなもので微妙なコード実行を隠すことはおそらく不可能ではありませんが、リスクはずっと低くなります。

    私は別のものを提案しましょう。表現を評価するためにサンドボックスを使用した場合はどうなりますか?例えばthisを見てください。コードで使用できる関数を数学関数のみに簡単に制限することができます。また、サンドボックスを信頼する限り、悪意のあるものは実行されないことが保証されます。これは、問題を第三者に負担させることになります(あなたはこれを信頼しなければなりません、これは重要な決定です)、あなたのコードは非常にシンプルで合理的に安全なままです。あなたが探検したいかもしれない他のサンドボックスもあります。

    関連する問題