I have an input-based string looking like this: "34*(12+45.67)>=44-53" and i need to know if its true or false. So, if the string contains only digits and */+-().<>= is it safe to use eval? Or maybe there is some better solution for this?
-
This answer should help: http://stackoverflow.com/a/951868/2287470 – Joe Jun 07 '13 at 17:01
-
1Do yourself a favour and use a proper calculator - http://stackoverflow.com/questions/12692727/how-to-make-a-calculator-in-php - especially as (in addition to all its other issues) eval() is useless for reporting errors – Mark Baker Jun 07 '13 at 17:02
-
After doing your checks and sanatizing it might be better to call `create_function` on the expression then call that function as well to further sandbox the expression. – Orangepill Jun 07 '13 at 17:07
6 Answers
Yes, there is nothing that can be done with that input that is unsafe. So long as you check as follows:
if( preg_match("([^0-9*/+().<>=-])",$input)) die("Invalid input");
Then you will be fine. However, be aware that the input must be syntactically correct. Something like >><>>><><>>>>>
would pass the check, but cause an error. You should wrap a try..catch
block around your eval
.
Ideally, however, this should really be handled in JavaScript if you can. It's okay to use eval
on the user's own provided data.

- 320,036
- 81
- 464
- 592
The safety of eval depends on where the data is coming from, and what it contains. If you've confirmed that it only contains digits and mathematical operations, it should be fine.
Note that you would need to parse it and convert it into a PHP statement, as that alone will always return an error. Remember PHP uses == for comparison, and you'll need a variable or two.

- 7,075
- 28
- 39
eval
is never safe on its own, if you're evaluating user input. If you follow that path, then all security is up to you. If your code has the capacity to mess with sensitive things anywhere, then good luck working out and preventing all the thousands of ways malicious users could screw your application.
Otherwise, if all you have is a sandbox page somewhere that couldn't touch the server to save its life, then yes, you're safe.

- 9,229
- 4
- 42
- 62
-
What do you mean by "on its own"? Yes, basically i wanna eval user input. Before it im goona check if its only digits and */+-().<>= . If you think its not safe, please, tell me why as well. – Alena Jun 07 '13 at 17:05
-
It's not safe *on its own* because security in this case is solely *your own responsibility*, not the code's. There is no text anywhere saying that `eval` prevents this or that kind of hack from being done, and it opens up a security breach on your application. So your code is only as safe as **you** can make it. In other words: without `eval` (and other breaches, like SQL Injection), you're as safe as PHP is safe. With `eval`, you are as safe as your technique is safe, because now the weak link is you. – Geeky Guy Jun 07 '13 at 17:12
-
Speaking of injections, this might interest you. Just food for thought: http://en.wikipedia.org/wiki/Code_injection#Dynamic_evaluation_vulnerabilities_-_eval_injection – Geeky Guy Jun 07 '13 at 17:14
You could strip out characters you don't want, just to be safe:
$x = preg_replace('/[^0-9+\-\*\/()>=]/', '', $input);
eval($x);
That will remove anything that is not in 0,1,2,3,4,5,6,7,8,9,0,/,+,-,*,(, or )

- 62,300
- 5
- 72
- 93
If your code directly takes the user input and evaluates it:
eval($_POST['myInput'])
then no, it is not safe to use eval. However, you can make it safe to use eval by parsing the string, possibly with a regular expression beforehand,. For example, ensuring that it is composed of only numbers, mathematical operators, and comparison operators will likely do the trick.

- 5,941
- 1
- 24
- 39
If, and only if, that string is
- built entirely under your control, with no user input being copied in; or
- already parsed, so that you can guarantee it will always contain only digits and basic math symbols in a valid order;
then eval
is safe. Otherwise, at the very least, someone can trigger a parse error.

- 84,970
- 20
- 145
- 172