Is Eval a good guy or a bad guy?

Speak very poorly of eval, but sometimes I wonder if he really is the problem or is the person who is sitting in front of the computer (the programmer support).

My whole life (in programming) I have heard criticism, jokes, zoos over this function eval, but the curious thing is that, even those who zoom, end up using libraries that use it internally, without knowing it.

An example of this is Laravel 3, which in the system of views , use eval.

Example (removed comments from 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;
}

GITHUB-view.php-line 385

It is true, it is already discontinued, but it is not in such a distant era (the version of it is for PHP 5.3). But it would not be surprising if one of the critics of eval had used this framework without knowing this information.

And yet I give another example, which many programmers also use, but without knowing it. We SuperClosure that is used in Laravel 4 and Laravel 5. This library aims to provide 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 the information passed 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 classes of the libraries presented above, remembering that they are only two examples, but there must be other cases, I wondered if I should still keep talking bad about eval or simply do an analysis and evaluate when it is good or bad to use it.

On the other hand, if I think that " every eval, regardless of how it is implemented, it's a risk", I'll probably have to stop using the libraries I cited above, and do a whole manual job...

  • 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't that put my code at risk?

  • The eval must be used in some very specific cases (for example, only in code generation) or can I use it freely, as long as I am aware of what I am doing?

Note : please do not edit and put tags as php or laravel, as the examples were only to show cases where eval was "well received". If there are examples of other languages that use it, you are welcome.

 38
Author: Wallace Maxters, 2016-05-16

2 answers

I'm going to start by saying that people use libraries without knowing if they have quality or not. Thus, how they use techniques, tools, methodologies, paradigms, technologies, courses, etc. not knowing if it's good for him in that context.

What are the risks of using eval in a project?

By injecting malicious code or data it is possible to compromise the entire execution system. eval() will execute the text it receives without any concern. Often the programmer imagines that something reliable will come, but the opposite usually happens .

Should I always avoid it?

Yes, you should avoid it "always". But if you have a real need you can use it if you know what you're doing.

If the answer is yes to "should I avoid it", then should I also stop using libraries that implement it? After all, can't that put my code at risk?

If the library is fine made there is not a big problem. I wonder if the library used this because its programmers are lazy or there was a real reason for its use. If it is the first, this reason alone should be a warning not to use this library.

The decision must go through an analysis of the code and see if they have sanitized all function input properly. If this was done the danger is small. It can always fail. It may be that they did almost right, but left a gap that some change in the code may pave the way for a vulnerability.

Should eval be used in some very specific cases (for example, only in code generation) or can I use it freely, as long as I am aware of what I am doing?

If I'm going to use code generation the right way, I have doubts if eval() is really necessary. If it is something that is not exposed, it is already something positive. You can even use it freely if you are conscious of what you are doing, but if you do, you will not use it unless it is fundamental. Sanitizing can be more complicated than the person imagines. Of course it always has exceptions, but when there are some, it was usually simple to solve without eval() since it does not need to sanitize anything.

Utility of eval ()

I don't remember a problem I had to deal with that eval() was necessary unless I used a very bad language that didn't allow other ways. Just for having an idea was a language that did not have array , function, and reference. The day this language spent having these things, it all worked out without evaluating source code at runtime.

Doing right with it is so complicated that doing right without it is just as or easier. Almost every use of the function only gets simpler if it leaves gaps.

Deep down the eval() itself is not the problem, at least no more than SQL. Of course the eval() allows to cause greater damage (but it may even be smaller in certain cases). The danger is not to sanitize the text.

It is obvious that in scripts own, internal, very simple things, or even in cases where the text source is controlled 100% by the application, its use can be minimally adequate, although probably not yet necessary.

In addition to the security issue there are performance and maintainability issues. Therefore, even in cases where safety is not a problem, it is advisable not to abuse.

The danger of it is that it is addictive. The person likes to have the work seemingly simplified, and begins to abuse.

JavaScript

Interestingly the staff speaks very poorly of eval() in JavaScript. In fact it is better to avoid it, but think about it, what difference does it make to have a eval() in a code that the user has total control over? The JS problem is further down. Of course I speak of the use in the browser. If you use Node, Deno, or other technology for use on the backend , the eval() should be avoided, or at least use with perfect sanitization.

 30
Author: Maniero, 2020-10-26 13:50:20

Consider that every technique, pattern, or programming philosophy you learn is a weapon.

Algorithms with data structures are a gun, you need to learn to handle at least that if you want to go to the front of battle. Hence the object orientation, which is a rifle - you only become an efficient soldier when you can assemble and disassemble your objects with your eyes closed. Design standards are Sniper Rifles, you destroy specific problems with a lot precision. Algorithm analysis (understand complexity and notation O) is a missile launcher - no matter how much the problem grows, you will spend the same ammunition to end it.

The eval is like an intercontinental ballistic nuclear missile:

  • has the potential to solve problems that would be very difficult to solve otherwise. In this case, inclusion of external files, as Laravel does. But...
  • public opinion will hate you. You will to hear from many people that what you are doing is an atrocity;
  • will have a lot of collateral damage: you are potentially opening your code to Javascript injection vulnerabilities. On the client side (browser) this is not so serious because in general all the code that runs in the browser is exposed to malicious people. But if you use JS on the server (node.js, for example) and performs eval on something that comes from the client side... May the God of programming have mercy on his soul;
  • radiation takes centuries to dissipate - maintaining your code is getting more and more complicated, as:
    ** Virtually no code analysis tool will want to pull over on eval;
    ** Debugging becomes much more complicated;
    ** Flows become harder to map.

To conclude, I will speak from my own experience. Most of the time people use eval, they could have solved their problems by other means. In an attempt to mitigate the problems cited above, they end up doing more things that are not recommended and maintenance costs have seen a snowball. If you think about using eval, make sure that your problems cannot be solved in any other way before taking the idea forward.

 13
Author: Garoto de Programa, 2016-05-17 03:08:06