关于如何避免使用eval(parse(...))
这引发了一些问题:
eval(parse())
? get()
草率更危险吗?)答案 0 :(得分:39)
由于安全问题,针对eval(parse(...))
的大多数论据都出现而不是,毕竟,没有人声称R是一个暴露于互联网的安全接口,而是因为这样代码通常是使用不那么模糊的方法来完成的事情,即既快又更人性化的方法。 R语言应该是高级的,因此认知的偏好(我不认为自己在该组中)是看到既紧凑又富有表现力的代码。
所以危险在于eval(parse(..))
是一种绕过缺乏知识的后门方法,而提出这种障碍的希望是人们会改善他们对R语言的使用。门仍然打开,但希望更有表现力地使用其他功能。 Carl Witthoft's question earlier today说明不知道get
函数可用,并且question he linked to表示对[[
函数的行为方式缺乏了解(以及$
如何比[[
更有限。在这两种情况下都可以构建一个eval(parse(..))
解决方案,但它比其他方案更笨拙,更不清晰。
答案 1 :(得分:34)
如果您开始在另一个用户传递给您的字符串上调用eval,则只会出现安全问题。如果您正在创建在后台运行R的应用程序,这是一个大问题,但对于您编写要由您自己运行的代码的数据分析,您不必担心eval
的影响关于安全。
eval(parse(
的其他一些问题。
首先,使用eval-parse的代码通常比非分析代码更难调试,这是有问题的,因为调试软件首先是twice as difficult编写它。
这是一个错误的函数。
std <- function()
{
mean(1to10)
}
愚蠢的我,我已经忘记了冒号操作员并错误地创建了我的矢量。如果我尝试使用此函数,那么R会注意到问题并抛出错误,指出我的错误。
这是eval-parse版本。
ep <- function()
{
eval(parse(text = "mean(1to10)"))
}
此将来源,因为错误位于有效字符串中。只是稍后,当我们运行代码时才会抛出错误。因此,通过使用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
答案 2 :(得分:17)
通常有一种比使用代码字符串更好的“计算语言”的方法;根据我的经验,evalparse重码需要很多安全防护来保证合理的输出。
通常可以通过直接将R代码作为语言对象来解决相同的任务; Hadley Wickham在R here中有一个关于元编程的有用指南:
gtools库中的defmacro()函数是我最喜欢的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代码。有关此有用功能的更多信息,请参见here:
希望有所帮助!
答案 3 :(得分:8)
在某些编程语言中,
eval()
是一个评估函数 一个字符串,好像它是一个表达式并返回一个结果;在 其他人,它执行多行代码,就像它们一样 包括而不是包括eval的行。 eval的输入是 不一定是一串;在支持句法的语言中 抽象(如Lisp),eval的输入将包含抽象 句法形式。 http://en.wikipedia.org/wiki/Eval
如果eval使用不当,可以利用各种漏洞利用。
攻击者可以提供带有字符串的程序 “session.update(authenticated = True)”作为数据,将更新 会话字典将经过身份验证的密钥设置为True。要补救 这样,所有将与eval一起使用的数据必须被转义,或者它 必须运行而无法访问可能有害的功能。 http://en.wikipedia.org/wiki/Eval
换句话说,eval()
的最大危险是代码注入应用程序的可能性。使用eval()
也会导致某些语言出现性能问题,具体取决于所使用的内容。
特别是在R中,可能是因为您可以使用get()
代替eval(parse())
而且您的结果将是相同的,而不必诉诸eval()