Closed1

安全な?eval電卓

inouehiinouehi

https://x.com/asumikam/status/1813904138465620341
https://x.com/tadsan/status/1813907250194350164
https://x.com/smeghead/status/1813949672232464882
にインスパイアされたPHP-Parserを用いたPoC。

https://github.com/nikic/PHP-Parser

<?php
require dirname(__FILE__) . '/vendor/autoload.php';

use PhpParser\Error;
use PhpParser\ParserFactory;
use PhpParser\{Node, NodeTraverser, NodeVisitorAbstract};

$formula = "3 + 4 * 4 / 2 - 1";

$parser = (new ParserFactory())->createForNewestSupportedVersion();

try {
    $ast = $parser->parse('<?php ' . $formula . ';');
} catch (Error $error) {
    echo "Parse error: {$error->getMessage()}\n";
    return;
}

$traverser = new NodeTraverser;
$traverser->addVisitor(new class extends NodeVisitorAbstract {
    public function enterNode(Node $node) {
        if ($node instanceof Node\Stmt\Expression && $node->expr instanceof Node\Expr\BinaryOp
            || $node instanceof Node\Expr\BinaryOp
            || $node instanceof Node\Scalar\Int_
            || $node instanceof Node\Scalar\Float_
        ) {
            return $node;
        }
        throw new \RuntimeException('invalid expression.');
    }
});

try {
    $traverser->traverse($ast);
} catch (Error $error) {
    echo "Validation error: {$error->getMessage()}\n";
    return;
}

echo eval(sprintf('return %s;', $formula));
このスクラップは3ヶ月前にクローズされました