05 giugno, 2019

eval() considerata pericolosa - non sempre vero


Io sono vecchio e alle volte non solo si vede ma trasmetto le mie abitudini anche a persone perfettamente normali, li travio. Adesso illustro un esempio, se del caso non leggete.

Serve intanto ambientare la scena: è quella in cui c'è un 'puter (non importa quale) ma non un telefono a portata di mano (o se c'è ignorarlo) e si è troppo pigri (lazy) per fare il calcolo con carta e penna. OK, c'è la calcolatrice, da qualche parte c'è l'icona o una voce di un menu o qualcosa di simile, ne sono quasi sicuro, anzi sicurissimissimo.

Però si può anche, più semplicemente (per noi vecchi), ricorrere a un qualsiasi linguaggio di programmazione, di quelli dinamici, interattivi, una volta sarebbe stato il Basic oggi --sai l'evoluzione... Siccome non sono razzista uso JavaScript:

* eval-arm $ node
> 37 * 73 / 13
207.76923076923077
>

Semplice vero? comodo vero? Quando una cosa l'hai fatta almeno un paio di volte --si dice-- la farai ancora e allora conviene automatizzarla. Che vorrebbe dire qualcosa così:

#!/usr/bin/node

expr = process.argv[2]
r = eval(expr)
console.log(r)


che si esegue così:

* eval-arm $ node xcjs "37 * 73 / 13"
207.76923076923077
* eval-arm $

Nel mio caso avevo inizialmente creato uno script che utilizzava bc, poi visto che c'è anche Windows e sono niubbo con Node.js sono passato a Python. Eccone una versione embrionale, elementare, un inizio da sviluppare:

#!/usr/bin/python3

from sys import argv
from math import e, pi, pow # e altre funzioni che voglio usare

if len(argv) <= 1:
    print("manca l'espressione")
    exit(2)

expr = argv[1]
expr = expr.replace('^', '**')

try:
    r = eval(expr)
except:
    r = expr + ": errore!"

print(r)


eseguo:

* eval-arm $ py3 xc.py "37 * 73 / 13"
207.76923076923077
* eval-arm $ py3 xc.py "TT 37 * 73 / 13"
TT 37 * 73 / 13: errore!
* eval-arm $


OK, funziona. E si possono fare calcoli più complessi:

* eval-arm $ py3 xc.py "pow(37 * 73, 1/2) / 13^2"
0.30752157302216054
* eval-arm $ py3 xc.py "pi^e - e^pi"
-0.6815349144182221
* eval-arm $


Notare che posso usare ^ per l'elevazione a potenza, è stata sufficiente 'istruzione expr = expr.replace('^', '**'). Resta da completare, inserire funzioni, sia di libreria che personali, aggiungere il formato per il risultato e altro ancora ma il più è fatto.

Però subito (anzi prima di subito (cit.)) salta fuori un'obiezione: l'uso di eval() è considerato cattiva programmazione.

Una googlata veloce ha dato una valanga (visto che non ho usato landslide?) di link:

MDN web docs, Moz://a
eval() is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run eval() with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension. More importantly, a third-party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways to which the similar Function is not susceptible.
eval() is also slower than the alternatives, since it has to invoke the JS interpreter, while many other constructs are optimized by modern JS engines.


Don't be eval()
JavaScript is an interpreted language, and like so many of its peers it includes the all powerful eval() function. eval() takes a string and executes it as if it were regular JavaScript code. It’s incredibly powerful and incredibly easy to abuse in ways that make your code slower and harder to maintain. As a general rule, if you’re using eval() there’s probably something wrong with your design.
Some programmers say that
eval() is B.A.D. – Broken As Designed – and should be removed from the language. However, there are some places in which it can dramatically simplify your code.

Why does eval() exist?
eval() exists because sometimes you want to give complete programmatic control of your application to code passed in at run time.

Why is using `eval` considered bad in JavaScript?
I heard the speaker in a meetup say, “You’re either evil, or just plain stupid if you use eval in your code”. Is there are any grain of truth behind the above statement?
I think it's one of those superstitious things that's based on truth where there is an element of truth to it, and because of this people avoid it religiously without understanding why. But just because somebody knows avoid it without knowing why doesn't mean they're wrong to avoid it. But it sure does make it difficult to ask questions about it and learn how to use it correctly.
It seems the only good use-case for eval() is interpreting JavaScript code contained within another language. Let's say you have some raw text, and some of that text is JS, you could use
eval() to turn the quoted JavaScript back into JavaScript and execute it. When that is the task you need to do, eval() is the only thing that will work, but it's very rare that you're needing to execute quoted JavaScript code from another language (and this should be done with caution when you do).

eval() isn’t evil, just misunderstood
Despite popular theory (and Crockford’s insistence), the mere presence of eval() does not indicate a problem. Using eval() does not automatically open you up to a Cross-Site Scripting (XSS) attack nor does it mean there is some lingering security vulnerability that you’re not aware of. Just like any tool, you need to know how to wield it correctly, but even if you use it incorrectly, the potential for damage is still fairly low and contained.

Is eval evil?
There is a high chance that you’ve stumbled across the JavaScript eval function.  It is a common knowledge that in JavaScript, eval is something that is a bad practice. Have you ever wondered how it works and why exactly a lot of people discourage it? This article covers that and presents some real-life usage of the eval function.
The
eval function takes the JavaScript code in the form of a string and evaluates it. It is quite a dangerous function to use. It is because of the fact it executes the code with the same privileges as the rest of the application. The code ran by eval also uses the same scope. If you use eval with a string that can be in any way affected by someone, you may face the harsh reality of it being malicious.

Eval is Evil, Part One
The eval method -- which takes a string containing JScript code, compiles it and runs it -- is probably the most powerful and most misused method in JScript. There are a few scenarios in which eval is invaluable.  For example, when you are building up complex mathematical expressions based on user input, or when you are serializing object state to a string so that it can be stored or transmitted, and reconstituted later.
However, these worthy scenarios make up a tiny percentage of the actual usage of
eval.  In the majority of cases, eval is used like a sledgehammer swatting a fly -- it gets the job done, but with too much power.  It's slow, it's unwieldy, and tends to magnify the damage when you make a mistake.  Please spread the word far and wide: if you are considering using eval then there is probably a better way.  Think hard before you use eval.

EVAL is evil? Using variables created dynamically - info retrieval
Uh! qui niente JS ma MATLAB; considerazioni interessanti, da leggere di là che non riporto.

Però tranne l'ultimo exhibit sono tutti relativi all'online (e Javascript) per ovvi problemi di sicurezza. Condizioni mooolto diverse dal caso qui considerato. E, al solito la Wiki la sa lunga (e ne ricorda l'origine: "Lisp was the original language to make use of an eval function in 1958. In fact, definition of the eval function led to the first implementation of the language interpreter". Ma se nomino il Lisp faccio scappare il lettore 🙁).

🔴

Nessun commento:

Posta un commento