eval(parse(…))的危险具体是什么?

有几个关于如何避免使用eval(parse(...))

  • R-evalparse -是-经常欠佳
  • 避免最声名狼藉-evalparse构build体

这引发了一些问题:

  • 为什么具体应该避免eval(parse())
  • 而最重要的是,有什么危险?
    • 如果代码不在生产中使用,是否有危险? (我在想,有任何回避意想不到的结果的危险,显然如果你不小心parsing什么的话,你会遇到问题,但是比get()更危险吗?

反对eval(parse(...))大多数论据并不是出于安全考虑,毕竟没有人声称R是暴露给互联网的安全接口,而是因为这样的代码通常会做可以使用较不明显的方法来完成,即既快速又更人性化的方法。 R语言应该是高层次的,所以认识的偏好(我不认为自己在这个群体中)是看代码既紧凑又有performance力。

所以危险的是, eval(parse(..))是一种绕过知识缺乏的后门方法,而提出这个障碍的希望是人们会改进对R语言的使用。 门仍然是开放的,但希望是更具performance力的使用其他function。 卡尔·威特福特(Carl Witthoft)今天早些时候提出的问题表明,不知道get函数是否可用,并且他提出的问题暴露出对函数performance(以及$如何比[[ )更有限)的缺乏理解。 在这两种情况下,都可以构build一个eval(parse(..))解决scheme,但是比其他scheme更加笨拙和不太清晰。

只有当您开始对另一个用户传递给您的string进行eval调用时,才会出现安全问题。 如果你正在创build一个在后台运行R的应用程序,这对你来说是个大问题,但是对于你自己编写代码的数据分析来说,你不需要担心eval对安全性的影响。

eval(parse(一些其他问题eval(parse(虽然。

首先,使用eval-parse的代码通常比非分析代码更难debugging,这是有问题的,因为debugging软件的难度比写在第一位的要困难一倍 。

这是一个错误的function。

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

傻了,我忘记了冒号操作符,错误地创build了我的向量。 如果我试着find这个函数,那么R会注意到这个问题,并且抛出一个错误,指出我的错误。

这是eval-parse版本。

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

源,因为错误是在一个有效的string内。 只是晚些时候,当我们来运行错误抛出的代码。 所以通过使用eval-parse,我们失去了源时间错误检查能力。

我也认为这个函数的第二个版本更难以阅读。

eval-parse的另一个问题是它比直接执行的代码慢得多。 比较

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

 system.time(for(i in seq_len(1e4)) eval(parse(text = "mean(1:10)"))) user system elapsed 1.54 0.14 1.69 

通常情况下,比使用代码string有更好的“计算语言”的方法; 根据我的经验,评估重码需要大量的安全防护来保证合理的输出。

通过直接将R代码作为语言对象进行处理,通常可以解决同样的任务。 在这里,哈德利·威克姆(Hadley Wickham)在R中有一个有用的元编程指南:

gtools库中的defmacro()函数是我最喜欢的替代品(不是半分类的R双关),用于evalparse构造

 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> 

这种方法的好处是你可以保证返回语法合法的R代码。 更多关于这个有用的function可以在这里find:

希望有所帮助!

在一些编程语言中, eval()是一个函数,它将string看作是一个expression式并返回一个结果; 在其他情况下,它执行多行代码,就好像它们被包括在内而不是包含eval的行一样。 eval的input不一定是一个string; 在支持语法抽象的语言(如Lisp)中,eval的input将由抽象语法forms组成。 http://en.wikipedia.org/wiki/Eval

如果eval使用不当,可以利用各种各样的漏洞。

攻击者可以提供一个string为“session.update(authenticated = True)”的程序作为数据,它将更新会话字典以将validation的密钥设置为True。 为了解决这个问题,所有与eval一起使用的数据必须被转义,或者必须运行而不能访问潜在的有害function。 http://en.wikipedia.org/wiki/Eval

换句话说, eval()的最大危险是可能将代码注入到应用程序中。 使用eval()也可能会导致某些语言的性能问题,具体取决于使用的内容。

特别是在R,这可能是因为你可以使用get()代替eval(parse()) ,你的结果将是相同的,而不必诉诸于eval()