I have to build an application which calculate some data. I do not know what calculations can be asked by scientists.
For example, User A will want to calculate (A + 5) * 3 User B will want to calculate (A + 14)² * pi
The arithmetics formula are defined by scientists and stored in database by administrator.
The simple way is to do :
<?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);
But Eval is evil as it is explained by @thpl in this answer
I have two options :
- To do a lot of analyze and tranform each character of formula and
create a great Calculation class. (Find the operand on each side of
a
+
and replace+
character by a call toaddition
method etc. etc. - Inspect
$formula
with a good (secured ?) regexp and call the evileval
function.
The first solution seems more secured but very long to develop.
For the second solution, I found this on php documentation :
<?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;
}
First question : Is the second solution sufficiently safe ?
I searched on the Internet(of course), but the best solution found is the previous code. Is there some php functions, pearl or PECL libraries to help me ? an arithmetic_eval
function ?
(I don't ask in Security.SE because my question only concerns php)