PHP   发布时间:2022-04-04  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了PHP EVAL-解决不安全问题大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

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

我发现执行这些计算之一的最简单方法是eval -尝试找出用于以下内容的解析器:

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

似乎很难.如果有人对此解决方案,我将很高兴听到.

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

因此,我提出一个问题,如果我进行了正则表达式,则删除了除数字,标准运算符(-/ *)和括号之外的所有内容,例如

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

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

解决方法:

我最近编码了一个使用BCMath函数PEDMAS compliant interpreter

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;
}

支持以下运算符:

> ^(战俘)
> *
> /
>%(模数)
>
>-
> =,==,&lt ;、< =,&gt ;、> =(比较)

您这样称呼它:

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

我这样做是为了让我有一个简单的方法来执行任意长度的计算,但是,在您的情况下,您也可以剥离所有空白并使用以下正则表达式验证字符:

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

大佬总结

以上是大佬教程为你收集整理的PHP EVAL-解决不安全问题全部内容,希望文章能够帮你解决PHP EVAL-解决不安全问题所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签: