1

このようなコードがあります。

eval('$ruleTrue = '."{$value} {$operator} {$value2};");

データベースから主に数値を取得し、それらを他の数値と比較しています。オペレーターもデータベースから取得されます。可能な演算子は <、>、== です。

int と float を比較すると、これは完全に機能します。しかし、文字列を比較すると壊れます。例えば..

動作: 5 > 4 $ruleTrue = true

正しく動作しない: John-Adams == Alice $ruleTrue = true <--- なぜ? ジョンはアリスにとって == ではないからです。

文字列を比較すると、何らかの理由で $ruleTrue 変数が true として返されます。

4

3 に答える 3

4

このコードを評価しようとしています:

$ruleTrue = John == Alice;

John文字列でAliceはなく、未定義の定数です。それらを引用符で囲みたいとします。ただし、ユーザーがデータベース内のこれらのフィールドを編集できる場合、文字列の引用符を外して独自の php コードを実行する方法を見つけてしまう可能性があるため、注意が必要です。そのように Eval は非常に安全ではないので、おそらく使用すべきではありません。

于 2012-12-20T21:46:41.793 に答える
2

式は、のJohn-Adams == Aliceように解析され(John - Adams) == Aliceます。左側は2つの文字列を減算しようとしています(未定義の定数は「ベアワード」と見なされ、名前の文字列化と同じです。John === 'John'たとえば)。このような奇妙な操作を理解するために、PHPは両方の文字列を次のように変換します。数字。整数として、両方の文字列の値は0であるため、左側は0になります。

int。

ここで、PHPがと比較したい場合、PHPは==両側を同じ型に強制変換したいと考えています。この場合、intに変換されます。 Alice また、0に変換されます。両側が0であるため、「明らかに」等しくなります。

これを防ぐには、値を引用符で囲む必要があります。===その型強制マジックが本当に必要でない限り、厳密な等号演算子()の使用を検討することもできます。

または、既知の演算子のセットがある場合は、eval演算子のサブ関数を持つ比較関数を作成することで、これを排除し、より安全で堅牢にすることができます。そのようです:

function compare($value1, $op, $value2) {
    static $known_ops = array(
        '==' => function($a, $b) { return $a == $b; },
        '!=' => function($a, $b) { return $a != $b; },
        ...

        # you can even make up your own operators.  For example, Perl's 'eq':
        'eq' => function($a, $b) { return "$a" === "$b"; }

        ...
    );
    $func = $known_ops[$op];
    return $func($value1, $value2);
}

...

$ruleTrue = compare($value, $operator, $value2);

今、あなたはあなたの価値観について心配する必要はありません。心配する必要はありますが$operator、それは、検証せずにユーザーに入力させた場合にのみ問題になります。その場合、例外など$opがない場合はスローする必要が$known_opsあります。PHPに処理を任せた場合、を呼び出そうとすると致命的なエラーが発生する可能性がありますnull

于 2012-12-20T21:57:45.053 に答える