¿Cuáles son específicamente los peligros de eval(analizar (par))?


Hay varias preguntas sobre cómo evitar usar eval(parse(...))

Que provoca las preguntas:

  • ¿Por qué Específicamente se debe evitar eval(parse())?
  • Y lo más importante, ¿Cuáles son los peligros?
    • ¿Hay algún peligro si el código no se utiliza en la producción? (Estoy pensando, cualquier peligro de volver resultados no deseados. Claramente si no tienes cuidado con lo que estás analizando, tendrás problemas. Pero, ¿es eso más peligroso que ser descuidado con get()?)
Author: Community, 2012-11-30

4 answers

La mayoría de los argumentos en contra de eval(parse(...)) surgen no debido a preocupaciones de seguridad, después de todo, no se afirma que R sea una interfaz segura para exponer a Internet, sino más bien porque dicho código generalmente hace cosas que se pueden lograr utilizando métodos menos oscuros, es decir, métodos que son más rápidos y más capaces de analizar humanos. El lenguaje R se supone que es de alto nivel, por lo que la preferencia de los cognoscenti (y no me considero en ese grupo) es ver código que es compacto y expresivo.

Así que el peligro es que eval(parse(..)) es un método de puerta trasera para superar la falta de conocimiento y la esperanza de levantar esa barrera es que la gente mejorará su uso del lenguaje R. La puerta permanece abierta, pero la esperanza es un uso más expresivo de otras características. La pregunta de Carl Witthoft del día de hoy ilustró el no saber que la función get estaba disponible, y la pregunta a la que vinculó expuso una falta de comprensión de cómo la función [[ se comportó (y cómo $ fue más limitada que [[). En ambos casos se podría construir una solución eval(parse(..)), pero era más torpe y menos clara que la alternativa.

 40
Author: 42-,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:23

Las preocupaciones de seguridad solo surgen realmente si comienza a llamar a eval en cadenas que otro usuario le ha pasado. Esto es un gran problema si está creando una aplicación que ejecuta R en segundo plano, pero para el análisis de datos donde está escribiendo código para ser ejecutado por usted mismo, entonces no debería preocuparse por el efecto de eval en la seguridad.

Algunos otros problemas con eval(parse( sin embargo.

En primer lugar, el código que usa eval-parse suele ser mucho más difícil de depurar que el código no analizado, lo cual es problemático porque el software de depuración es el doble de difícil que escribirlo en primer lugar.

Aquí hay una función con un error.

std <- function()
{
  mean(1to10)
}

Tonto de mí, me he olvidado del operador de dos puntos y creado mi vector erróneamente. Si intento y fuente esta función, entonces R se da cuenta del problema y lanza un error, señalándome a mi error.

Aquí está la versión eval-parse.

ep <- function()
{
  eval(parse(text = "mean(1to10)"))
}

Este será fuente, porque el error está dentro de un cadena válida. Es solo más tarde, cuando llegamos a ejecutar el código que se lanza el error. Así que al usar eval-parse, hemos perdido la capacidad de comprobación de errores en tiempo de origen.

También creo que esta segunda versión de la función es mucho más difícil de leer.

El otro problema con eval-parse es que es mucho más lento que el código ejecutado directamente. Comparar

system.time(for(i in seq_len(1e4)) mean(1:10))
   user  system elapsed 
   0.08    0.00    0.07

Y

system.time(for(i in seq_len(1e4)) eval(parse(text = "mean(1:10)")))
   user  system elapsed 
   1.54    0.14    1.69
 32
Author: Richie Cotton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-01 21:40:24

Por lo general, hay una mejor manera de 'computar en el lenguaje' que trabajar con cadenas de código; evalparse heavy-code necesita mucha protección para garantizar una salida sensata, en mi experiencia.

La misma tarea generalmente se puede resolver trabajando en código R como un objeto de lenguaje directamente; Hadley Wickham tiene una guía útil sobre meta-programación en R aquí :

La función defmacro() en la biblioteca gtools es mi sustituto favorito (sin juego de palabras a medias) para la evalparse construct

require(gtools)

# both action_to_take & predicate will be subbed with code

F <- defmacro(predicate, action_to_take, expr = 
    if(predicate) action_to_take)

F(1 != 1, action_to_take = print('arithmetic doesnt work!'))

F(pi > 3, action_to_take = return('good!'))
[1] 'good!'

# the raw code for F
print(F)

function (predicate = stop("predicate not supplied"), action_to_take = stop("action_to_take not supplied")) 
{
    tmp <- substitute(if (predicate) action_to_take)
    eval(tmp, parent.frame())
}
<environment: 0x05ad5d3c> 

El beneficio de este método es que está garantizado para volver sintácticamente-código R legal. Más sobre esta útil función se puede encontrar aquí :

Espero que ayude!

 17
Author: RyanGrannell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-02 10:44:41

En algunos lenguajes de programación, eval() es una función que evalúa una cadena como si fuera una expresión y devuelve un resultado; en otros, ejecuta múltiples líneas de código como si hubieran sido incluido en lugar de la línea que incluye la evaluación. La entrada para evaluar es no necesariamente una cadena; en lenguajes que soportan sintáctica abstracciones (como Lisp), la entrada de eval consistirá en abstractos formas sintácticas. http://en.wikipedia.org/wiki/Eval

Hay todo tipo de exploits que uno puede aprovechar si eval se utiliza incorrectamente.

Un atacante podría suministrar un programa con la cadena "sesion.update (authenticated = True) " como datos, lo que actualizaría el diccionario de sesión para establecer que una clave autenticada sea True. Remediar esto, todos los datos que se utilizarán con eval deben ser escapados, o debe ejecutarse sin acceso a elementos potencialmente dañinos función. http://en.wikipedia.org/wiki/Eval

En otras palabras, el mayor peligro de eval() es el potencial de inyección de código en su aplicación. El uso de eval() también puede causar problemas de rendimiento en algunos idiomas dependiendo de para qué se está utilizando.

Específicamente en R, es probablemente porque puede usar get() en lugar de eval(parse()) y sus resultados serán los mismos sin tener que recurrir a eval()

 7
Author: ORION,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-30 17:57:06