When is eval evil in php?
eval is equally "evil" at all times.
If you see it as evil, then it's equally evil at all times. The reasons many describe it as evil don't go away with context.
Using eval() is generally a bad idea because it decreases readability of code, it impairs the ability for you to predict the code path before runtime (which has possible security implications), and hence affects the ability to analyze and debug code. Using eval() can also prevent the evaluated code and the code surrounding it from being optimised by an opcode cache such as the Zend Opcache integrated into PHP 5.5 and above, or by a JIT compiler such as the one in HHVM.
Furthermore, there is no situation for which it is absolutely necessary to use eval() - PHP is a fully-capable programming language without it. Regardless of what you want to use eval() for, there will be another way of doing it, in PHP.
Whether or not you actually see these as evils or you can personally justify using eval() is up to you. To some, the pitfalls are too great to ever justify it, and to others, eval() is a handy shortcut.
eval is evil when there is only the slightest possibility that userinput is included in the evaluated string. When you do eval without content that came from a user, you should be safe.
Nevertheless you should think at least twice before using eval, it looks deceivingly simple, but with error handling (see VBAssassins comment), debuggability etc. in mind, it is not so simple anymore.
So as a rule of thumb: Forget about it. When eval is the answer you're propably asking the wrong question! ;-)
I would be cautious in calling eval() pure evil. Dynamic evaluation is a powerful tool and can sometimes be a life saver. With eval() one can work around shortcomings of PHP (see below).
The main problems with eval() are:
- Potential unsafe input. Passing an untrusted parameter is a way to fail. It is often not a trivial task to make sure that a parameter (or part of it) is fully trusted.
- Trickiness. Using eval() makes code clever, therefore more difficult to follow. To quote Brian Kernighan "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it"
The main problem with actual use of eval() is only one:
- Inexperienced developers who use it without enough consideration.
As a rule of thumb I tend to follow this:
- Sometimes eval() is the only/the right solution.
- For most cases one should try something else.
- If unsure, goto 2.
- Else, be very, very careful.
In this case, eval is probably safe enough, as long as it's never possible for arbitrary columns to be created in a table by a user.
It's not really any more elegant though. This is basically a text parsing problem, and abusing PHP's parser to handle is seems a bit hacky. If you want to abuse language features, why not abuse the JSON parser? At least with the JSON parser, there's no possibility at all of code injection.
$json = str_replace(array(
'enum', '(', ')', "'"), array)
'', '[', ']', "'"), $type);
$result = json_decode($json);
A regular expression is probably the most obvious way. You can use a single regular expression to extract all the values from this string:
$extract_regex = '/
(?<=,|enum\() # Match strings that follow either a comma, or the string "enum("...
\' # ...then the opening quote mark...
(.*?) # ...and capture anything...
\' # ...up to the closing quote mark...
/x';
preg_match_all($extract_regex, $type, $matches);
$result = $matches[1];