【发布时间】:2016-12-05 17:25:37
【问题描述】:
我必须构建一个计算一些数据的应用程序。我不知道科学家可以问什么计算。
例如, 用户 A 将要计算 (A + 5) * 3 用户 B 将要计算 (A + 14)² * pi
算术公式由科学家定义并由管理员存储在数据库中。
简单的方法是:
<?php
//Formula is initialized by a query in database
$formula= '(A + 3) * 5';
//$ value is an integer entered by UserA and verify by Controller
$value = 42;
$arithmetic = str_replace('A', $formula, $value);
$result = eval($arithmetic);
但是 Eval 是邪恶的,正如 @thpl 在 answer 中所解释的那样
我有两个选择:
- 对公式的每个字符进行大量分析和转换,
创建一个很棒的计算类。 (找到两边的操作数
+并通过调用addition方法等替换+字符。 等等。 - 使用良好的(安全的?)正则表达式检查
$formula并调用邪恶的eval函数。
第一个解决方案似乎更安全,但开发时间很长。
对于第二种解决方案,我在 php 文档中找到了这个:
<?php
$test = '2+3*pi';
// Remove whitespaces
$test = preg_replace('/\s+/', '', $test);
$number = '(?:\d+(?:[,.]\d+)?|pi|π)'; // What is a number
$functions = '(?:sinh?|cosh?|tanh?|abs|acosh?|asinh?|atanh?|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;
}
第一个问题:第二个解决方案是否足够安全?
我在互联网上搜索(当然),但找到的最佳解决方案是以前的代码。是否有一些 php 函数、pearl 或 PECL 库可以帮助我? arithmetic_eval 函数?
(我不问Security.SE,因为我的问题只涉及php)
【问题讨论】: