我必须构建一个计算一些数据的应用程序。不知道科学家们能问出什么计算。
例如, 用户 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)
最佳答案
我认为第一个解决方案(自定义解析器)非常复杂且容易出错。其中最高的风险是仍然允许攻击者运行任意代码的漏洞。也许你可以做对,但很容易出错。
第二种解决方案(提议的基于正则表达式的验证)好坏不好说。分析 PHP 语法、将其与问题中的正则表达式进行比较、查看 PHP 中有哪些微妙的方式来编写语句和表达式等将花费大量时间。虽然乍一看它看起来并不灾难,但没有人无需很多分析就可以说它是安全的。在那之前使用它会非常危险。
您可能决定接受其中任何一种风险,因为您是说这些公式将由管理员存储。管理员可以查看这些公式是否是似乎不包含任何代码的真正数学公式。虽然在看起来像公式的东西中掩盖一些微妙的代码执行可能并非不可能,但如果受信任的管理员在实际使用和评估之前审查所有内容,风险就会低得多。
让我提出一些不同的建议。如果您使用沙箱来评估表达式会怎样?看看this例如。您可以轻松地将代码可用的函数限制为仅数学函数,只要您信任沙箱,就可以放心,不会运行任何恶意软件。这会将问题转移给第三方(然后您必须信任第三方,这是一个重要的决定!),并且您的代码将保持非常简单但相当安全。您可能还想探索其他沙箱。
关于php - 如何评估算术微积分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40979899/