【问题标题】:Securely evaluate simple maths安全地评估简单的数学
【发布时间】:2012-08-24 19:07:18
【问题描述】:

我想知道是否有一种安全的方法来评估数学,例如

2+2
10000+12000
10000-20
2 + 2
40 - 20 + 23 - 12

不必使用eval(),因为输入可以来自任何用户。我需要实现的只是整数的加减法。

是否有任何已经存在的 sn-ps,或者我没有遇到过的任何 PHP 函数?

【问题讨论】:

  • 你可以先清理输入(比如使用正则表达式只允许数字和数学运算符)
  • 您是否从用户输入中获取整个字符串?

标签: php


【解决方案1】:

考虑到 PHP 中提供的各种数学函数,我会质疑使用 eval。您说过您只想做简单的数学运算——使用eval 的唯一原因是执行更复杂的运算,或者从用户那里完全接受方程式。

如果您只想加减,请使用intval 清理输入并前往城镇:

$number1 = '100';
$number2 = 'shell_exec(\'rm -rf *\')';
echo intval($number1) + intval($number2); // 100

试试看:http://codepad.org/LSUDUw1M

这是因为intval 会忽略任何非数字。

如果您确实从用户输入(即100 - 20)中获得了整个方程式,则可以使用preg_replace 删除除允许的运算符和数字之外的任何内容:

$input = '20 + 4; shell_exec(\'rm *\')';
$input = preg_replace(
    '/[^0-9+-]/', 
    '',
    $input
);
eval('$result = '.$input.';');
echo 'result: '.$result; // 24

试试看:http://codepad.org/tnISDPJ3

在这里,我们使用的是正则表达式/[^0-9+-]/,它匹配任何非 0-9 OR + OR - 并将其替换为空字符串。

如果您想更深入地了解允许的方程式,请直接从eval 手册页获取:

// credit for code to bohwaz (http://www.php.net/manual/en/function.eval.php#107377)
$test = '2+3*pi';

// Remove whitespaces
$test = preg_replace('/\s+/', '', $test);

$number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number
$functions = '(?:abs|a?cosh?|a?sinh?|a?tanh?|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;
}

文档

【讨论】:

  • 我猜我已经尝遍了 eval 的全部内容。
【解决方案2】:

你可以自己解析表达式。

类似这样的:

// Minus is the same as plus a negative
// Also remove spaces after minus signs
$str = preg_replace('/-\s*(\d+)/', '+-$1', $str);

// Split on plusses
$nums = explode('+', $str);

// Trim values
$nums = array_map('trim', $nums);

// Add 'em up
echo array_sum($nums);

演示:http://codepad.org/ANc0gh27

【讨论】:

  • 我只是快速将它破解了,很高兴它有帮助:-)
【解决方案3】:

我在计算器脚本中使用了这种方法。

$field1 = $_GET["field1"];
$field2 = $_GET["field2"];

$answer = $field1 + $field2;
echo "$field1 + $field2 = $answer";

【讨论】:

  • 这个实际上并没有真正起作用,也没有真正做我需要它做的事情。
  • 哦,但是这很好用,但不知道它是否不适用于您的情况..对不起.....
  • 其实就是加一个值相同的值,基本上是在做x + x = y。
  • 好的,feild1 = 10 和 feild2 = 15 是什么,显然答案不相等?
  • @Manhim:这只是一个例子。显然每个$_GET 应该得到一个不同的变量。
猜你喜欢
  • 2023-03-29
  • 2011-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多