They speak very poorly of eval
, but sometimes I wonder if it really is the problem or it is the person who is sitting in front of the computer (I support the programmer).
My entire life (in programming) I've heard criticisms, jokes, zoeiras on top of this eval
function, but the curious thing is that even those who mock, end up using libraries that use it internally, without knowing it. p>
An example of this is Laravel 3
, which in the views system, uses eval
.
Example (I removed comments from the original code):
public function get()
{
$__data = $this->data();
$__contents = $this->load();
ob_start() and extract($__data, EXTR_SKIP);
try
{
eval('?>'.$__contents);
}
catch (\Exception $e)
{
ob_get_clean(); throw $e;
}
$content = ob_get_clean();
if (Event::listeners('view.filter'))
{
return Event::first('view.filter', array($content, $this->path));
}
return $content;
}
True, it's already discontinued, but it's not in a distant era like this (its version is for PHP 5.3). But it would not be surprising if one of the critics of eval
had used this framework without knowing that information.
And yet I give another example, which many programmers also use, but without knowing it. The SuperClosure that is used in Laravel 4 and Laravel 5. This library has the purpose of providing a possibility to serialize closures in PHP, since natively closures in PHP do not support serialization. This library becomes useful for those who need to use queuing systems, such as Beanstalkd, where past information is usually a string , and therefore the data in PHP needs to be serialized.
Example:
/**
* Reconstruct a closure.
*
* HERE BE DRAGONS!
*
* The infamous 'eval()' is used in this method, along with the error
* suppression operator, and variable variables (i.e., double dollar signs) to
* perform the unserialization logic. I'm sorry, world!
*
* This is also done inside a plain function instead of a method so that the
* binding and scope of the closure are null.
*
* @param array $__data Unserialized closure data.
*
* @return Closure|null
* @internal
*/
function __reconstruct_closure(array $__data)
{
// Simulate the original context the closure was created in.
foreach ($__data['context'] as $__var_name => &$__value) {
if ($__value instanceof SerializableClosure) {
// Unbox any SerializableClosures in the context.
$__value = $__value->getClosure();
} elseif ($__value === Serializer::RECURSION) {
// Track recursive references (there should only be one).
$__recursive_reference = $__var_name;
}
// Import the variable into this scope.
${$__var_name} = $__value;
}
// Evaluate the code to recreate the closure.
try {
if (isset($__recursive_reference)) {
// Special handling for recursive closures.
@eval("\${$__recursive_reference} = {$__data['code']};");
$__closure = ${$__recursive_reference};
} else {
@eval("\$__closure = {$__data['code']};");
}
} catch (\ParseError $e) {
// Discard the parse error.
}
return isset($__closure) ? $__closure : null;
}
GitHub - SerializableClosure.php - line 187 .
Thinking about the usefulness of the library classes presented above, remembering that they are just two examples, but there must be other cases, I was wondering if I should still keep talking bad about eval
or just do an analysis and evaluate when it's good or bad to use it.
On the other hand, if I think that "every eval, regardless of how it's implemented, is a risk", I'll probably have to stop using the libraries I mentioned above, and do an all-manual job ... < p>
-
What are the risks of using
eval
in a project? -
Should I always avoid it?
-
If the answer is yes to "should I avoid it," then should I also stop using libraries that implement it? After all, can not this put my code at risk?
Note : Please do not edit and put tags as php or laravel , since the examples were only to show cases where eval
was "well received". If there are examples of other languages that use it, you will be welcome.