gpt4 book ai didi

PHP EVAL - 解决不安全问题

转载 作者:可可西里 更新时间:2023-11-01 01:06:01 25 4
gpt4 key购买 nike

我们有一个系统必须执行用户输入提供的计算。

我发现进行其中一种计算的最简单方法是 eval —— 尝试找出一个解析器用于:

(3 + 6 ) / 2 + 27 * 5 / 2

只是看起来很难。如果有人对此有解决方案 - 我很乐意听到。

假设您要使用 EVAL(我知道它的可怕功能),允许他们在该框中键入他们想要的任何内容将是一个主要的不安全因素。

所以,我提出这个问题,如果我做一个正则表达式,删除除数字、标准运算符 (+ -/*) 和括号之外的所有内容,比如

$equation = preg_replace( '/[^0-9+-\/*()]/', '', $input_equation );
$result = eval( $equation );

系统是否可能发生任何危害?

最佳答案

我最近编写了一个 PEDMAS compliant interpreter使用 BCMath功能:

function BC($string, $precision = 32)
{
if (extension_loaded('bcmath') === true)
{
if (is_array($string) === true)
{
if ((count($string = array_slice($string, 1)) == 3) && (bcscale($precision) === true))
{
$callback = array('^' => 'pow', '*' => 'mul', '/' => 'div', '%' => 'mod', '+' => 'add', '-' => 'sub');

if (array_key_exists($operator = current(array_splice($string, 1, 1)), $callback) === true)
{
$x = 1;
$result = @call_user_func_array('bc' . $callback[$operator], $string);

if ((strcmp('^', $operator) === 0) && (($i = fmod(array_pop($string), 1)) > 0))
{
$y = BC(sprintf('((%1$s * %2$s ^ (1 - %3$s)) / %3$s) - (%2$s / %3$s) + %2$s', $string = array_shift($string), $x, $i = pow($i, -1)));

do
{
$x = $y;
$y = BC(sprintf('((%1$s * %2$s ^ (1 - %3$s)) / %3$s) - (%2$s / %3$s) + %2$s', $string, $x, $i));
}

while (BC(sprintf('%s > %s', $x, $y)));
}

if (strpos($result = bcmul($x, $result), '.') !== false)
{
$result = rtrim(rtrim($result, '0'), '.');

if (preg_match(sprintf('~[.][9]{%u}$~', $precision), $result) > 0)
{
$result = (strncmp('-', $result, 1) === 0) ? bcsub($result, 1, 0) : bcadd($result, 1, 0);
}

else if (preg_match(sprintf('~[.][0]{%u}[1]$~', $precision - 1), $result) > 0)
{
$result = bcmul($result, 1, 0);
}
}

return $result;
}

return intval(version_compare(call_user_func_array('bccomp', $string), 0, $operator));
}

$string = array_shift($string);
}

$string = str_replace(' ', '', str_ireplace('e', ' * 10 ^ ', $string));

while (preg_match('~[(]([^()]++)[)]~', $string) > 0)
{
$string = preg_replace_callback('~[(]([^()]++)[)]~', __METHOD__, $string);
}

foreach (array('\^', '[\*/%]', '[\+-]', '[<>]=?|={1,2}') as $operator)
{
while (preg_match(sprintf('~(?<![0-9])(%1$s)(%2$s)(%1$s)~', '[+-]?(?:[0-9]++(?:[.][0-9]*+)?|[.][0-9]++)', $operator), $string) > 0)
{
$string = preg_replace_callback(sprintf('~(?<![0-9])(%1$s)(%2$s)(%1$s)~', '[+-]?(?:[0-9]++(?:[.][0-9]*+)?|[.][0-9]++)', $operator), __METHOD__, $string, 1);
}
}
}

return (preg_match('~^[+-]?[0-9]++(?:[.][0-9]++)?$~', $string) > 0) ? $string : false;
}

它支持以下运算符:

  • ^ (战俘)
  • *
  • /
  • % (模数)
  • +
  • -
  • = , == , < , <= , > , >= (比较)

你这样调用它:

echo BC('(3 + 6 ) / 2 + 27 * 5 / 2');

我这样做是为了让我有一种简单的方法来执行任意长度的计算,但在您的情况下,您最好去掉所有空格并使用以下正则表达式验证字符:

if (preg_match('~^(?:[0-9()*/%+-<>=]+)$~', $expression) > 0) {
// safe to eval()
}

关于PHP EVAL - 解决不安全问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10843950/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com