[Python] alternative ad eval
Manlio Perillo
manlio.perillo a gmail.com
Mar 18 Mar 2014 13:39:27 CET
2014-03-17 22:57 GMT+01:00 Balan Victor <balan.victor0 a gmail.com>:
> Ho un array di tuple cosi formate da 3 elementi:
> (int|float|boolean|string|datetime|..., string, boolean). Es:
>
> [
> (10, "value >= 1", True),
> ("Ciao", "o in value", True),
> (True, "value == False", False),
> (92.5f, "value >= 92.0f", True),
> ]
> Il primo elemento della tupla può essere qualunque tipo o classe di python.
> Il secondo elemento è una espressione da applicare sulla tupla e che deve
> restituire True or False(value si riferisce al primo elemento della tupa)
> Il terzo elemento è il risultato dell'operazione appena sopra.
>
> A intervalli regolari ho bisogno di scorrere l'array sopra e aggiornare il
> valore del terzo elemento.
> Ho pensato di usare eval in questo modo:
>
> def check_status(value, eval_string):
> rc = eval(eval_string)
> if rc is not bool: raise WrongEvalString()
> return rc
>
> Conosco i rischi di eval e vorrei evitare di usarlo però non riesco a
> trovare nulla di altrettanto semplice e con le stesse potenzialità.
>
>
eval è relativamente sicuro, dato che può eseguire solo espressioni, e non
statement completi come exec.
Lo puoi rendere ancora più sicuro limitando il namespace, ad esempio:
def expand_template(template, **kwargs):
from string import Template
return Template(template).substitute(**kwargs)
def eval_expression(expr_literal, value):
expr = expand_template(expr_literal, value=value)
return eval(expr, {}, {})
def check_status(value, eval_string):
rc = eval_expression(eval_string, value)
if rc is not True:
raise WrongEvalString()
check_status(10, "$value == 10")
Questo però non basta, devi avere il controllo anche su value, ad esempio
accettando solo stringhe secondo un dato protocollo, di cui farai il
parsing e validazione.
Il mio protocollo preferito è "Typed NetStrings":
"<typeid><len>:<literal>
Ad esempio per un intero:
"i3:777"
tale protocollo è facile da leggere, parsare e validare (perchè verboso)
NB: In realtà la stringa che fa la validazione può essere impostata solo da
> qualcuno di autorizzato quindi il rischio che mi cancelli tutto il fs non
> ci dovrebbe essere, e non dovrebbero nemmeno fare operazioni del tipo
> "value ** value" però in ogni caso vorrei trovare qualcosa che mi metta al
> sicuro da questo tipo di operazioni.
>
Riguardo operazioni non autorizzate sei abbastanza al sicuro, grazie al
fatto che eval esegue solo espressioni, ed al fatto che valuti solo oggetti
a te noti.
In caso di dubbi, leggi la grammatica di Python per sapere cosa può
contenere una espressione.
Riguardo "value ** value" temi un attacco di tipo DoS?
In questo caso se vuoi limitare anche le possibili espressioni, l'unica
alternativa e scriverti un tuo parser, come ti hanno già suggerito. Dai
una occhiata al modulo ast di Python.
Ciao Manlio
-------------- parte successiva --------------
Un allegato HTML è stato rimosso...
URL: <http://lists.python.it/pipermail/python/attachments/20140318/6cb38b6d/attachment.html>
Maggiori informazioni sulla lista
Python