Nathanael
Nathanael

Reputation: 7153

Evaluating PHP expression logic—but without eval()?

For a complex project I'm working on, I want administrators to be allowed to attach conditions to events using boolean expressions.

Example:

if (1 > 2 || (1 == 1 && 3 > 2)) [...]

The above would return TRUE.

eval() seems like an easy solution, but I am well aware of the security risks it presents. Does PHP provide a way to evaluate expressions like the above without actually evaluating other arbitrary PHP code? Options would be something that only evaluates mathematical expressions, or perhaps an eval() sanitizer that accepts a whitelist of functions.

Thanks for your help!

Upvotes: 1

Views: 517

Answers (1)

Andikac
Andikac

Reputation: 434

The best thing is as your suggestion "sanitizer", by using token_get_all

below (incomplete) snippet so you might get the idea

function evalExpression ($expression)
{
    $code = "return $expression;";
    $token = token_get_all($code,TOKEN_PARSE);

    # return
    unset($token[1]);

    foreach ($token as $key=>$value) {

        if(is_array($value)) {

            # white list token
            $allow = [T_WHITESPACE,T_LNUMBER,/* add more token*/];

            # remove white list token
            if(in_array($value[0],$allow,true)) {
                unset($token[$key]);
            }

        } else {

            # white list string
            $allow = [';','>'/* add more element*/];

            # remove white list string
            if(in_array($value,$allow,true)) {
                unset($token[$key]);
            }

        }

    }

    # if token contain only white listed, $token should empty
    if(!$token) {
        return eval($code);
    } else {
        throw new \InvalidArgumentException('err'); 
    }

};

# return bool
var_dump(evalExpression('2 > 1'));

# should error
var_dump(evalExpression('function(){}'));

since eval construct are dangerous you should try to inject/test with malicious code, before run into production

Upvotes: 1

Related Questions