Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why exactly is eval evil?

People also ask

Is eval () bad?

eval() is evil if running on the server using input submitted by a client that was not created by the developer or that was not sanitized by the developer. eval() is not evil if running on the client, even if using unsanitized input crafted by the client.

Should you ever use eval?

Any code that is evil in EVAL, is evil in the browser itself. The attacker or anyone can easily inject a script node in DOM and do anything if he/she can eval anything. Not using EVAL will not make any difference. It is mostly poor server-side security that is harmful.

When should you use eval?

Eval function is mostly used in situations or applications which need to evaluate mathematical expressions. Also if the user wants to evaluate the string into code then can use eval function, because eval function evaluates the string expression and returns the integer as a result.

When should you use eval JavaScript?

Definition and Usage The eval() method evaluates or executes an argument. If the argument is an expression, eval() evaluates the expression. If the argument is one or more JavaScript statements, eval() executes the statements.


There are several reasons why one should not use EVAL.

The main reason for beginners is: you don't need it.

Example (assuming Common Lisp):

EVALuate an expression with different operators:

(let ((ops '(+ *)))
  (dolist (op ops)
    (print (eval (list op 1 2 3)))))

That's better written as:

(let ((ops '(+ *)))
  (dolist (op ops)
    (print (funcall op 1 2 3))))

There are lots of examples where beginners learning Lisp think they need EVAL, but they don't need it - since expressions are evaluated and one can also evaluate the function part. Most of the time the use of EVAL shows a lack of understanding of the evaluator.

It is the same problem with macros. Often beginners write macros, where they should write functions - not understanding what macros are really for and not understanding that a function already does the job.

It often is the wrong tool for the job to use EVAL and it often indicates that the beginner does not understand the usual Lisp evaluation rules.

If you think you need EVAL, then check if something like FUNCALL, REDUCE or APPLY could be used instead.

  • FUNCALL - call a function with arguments: (funcall '+ 1 2 3)
  • REDUCE - call a function on a list of values and combine the results: (reduce '+ '(1 2 3))
  • APPLY - call a function with a list as the arguments: (apply '+ '(1 2 3)).

Q: do I really need eval or does the compiler/evaluator already what I really want?

The main reasons to avoid EVAL for slightly more advanced users:

  • you want to make sure that your code is compiled, because the compiler can check code for many problems and generates faster code, sometimes MUCH MUCH MUCH (that's factor 1000 ;-) )faster code

  • code that's constructed and needs to be evaluated can't be compiled as early as possible.

  • eval of arbitrary user input opens up security problems

  • some use of evaluation with EVAL can happen at the wrong time and create build problems

To explain the last point with a simplified example:

(defmacro foo (a b)
  (list (if (eql a 3) 'sin 'cos) b))

So, I may want to write a macro that based on the first parameter uses either SIN or COS.

(foo 3 4) does (sin 4) and (foo 1 4) does (cos 4).

Now we may have:

(foo (+ 2 1) 4)

This does not give the desired result.

One then may want to repair the macro FOO by EVALuating the variable:

(defmacro foo (a b)
  (list (if (eql (eval a) 3) 'sin 'cos) b))

(foo (+ 2 1) 4)

But then this still does not work:

(defun bar (a b)
  (foo a b))

The value of the variable is just not known at compile time.

A general important reason to avoid EVAL: it is often used for ugly hacks.


eval (in any language) is not evil in the same way that a chainsaw is not evil. It is a tool. It happens to be a powerful tool that, when misused, can sever limbs and eviscerate (metaphorically speaking), but the same can be said for many tools in a programmer's toolbox including:

  • goto and friends
  • lock-based threading
  • continuations
  • macros (hygenic or other)
  • pointers
  • restartable exceptions
  • self-modifying code
  • ...and a cast of thousands.

If you find yourself having to use any of these powerful, potentially dangerous tools ask yourself three times "why?" in a chain. For example:

"Why do I have to use eval?" "Because of foo." "Why is foo necessary?" "Because ..."

If you get to the end of that chain and the tool still looks like it's the right thing to do, then do it. Document the Hell out of it. Test the Hell out of it. Double-check correctness and security over and over and over again. But do it.


Eval is fine, as long as you know EXACTLY what is going into it. Any user input going into it MUST be checked and validated and everything. If you don't know how to be 100% sure, then don't do it.

Basically, a user can type in any code for the language in question, and it will execute. You can imagine for yourself how much damage he can do.


"When should I use eval?" might be a better question.

The short answer is "when your program is intended to write another program at runtime, and then run it". Genetic programming is an example of a situation where it likely makes sense to use eval.


IMO, this question is not specific to LISP. Here is an answer on the same question for PHP, and it applies to LISP, Ruby, and other other language that has an eval:

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.
  • Trickyness. 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.

Taken from here.

I think the trickyness piece is an amazing point. The obsession with code golf and concise code has always resulted in "clever" code (for which evals are a great tool). But you should write your code for readability, IMO, not to demonstrate that you're a smarty and not to save paper (you won't be printing it anyway).

Then in LISP there's some problem related to the context in which eval is run, so untrusted code could get access to more things; this problem seems to be common anyway.


There have been many great answers but here is another take from Matthew Flatt, one of the implementers of Racket:

http://blog.racket-lang.org/2011/10/on-eval-in-dynamic-languages-generally.html

He makes many of the points that have already been covered but some people may find his take interesting nonetheless.

Summary: The context in which it's used affects the result of eval but is often not considered by programmers, leading to unexpected results.