我多次使用eval红宝石的功能.但我听说有人说evals很讨厌.当被问到为什么以及如何,我永远无法得到令人信服的理由不使用它.他们真的很讨厌吗?如果是,以什么方式?评估有哪些"更安全"的选择?
Mat*_*t J 33
如果您是eval由用户提交或可由用户修改的字符串,这相当于允许任意代码执行.想象一下,如果字符串包含OS调用rm -rf /或类似.也就是说,在您知道字符串被适当约束的情况下,或者您的Ruby解释器适当地沙箱化,或者理想情况下两者eval都可以非常强大.
如果您熟悉,问题类似于SQL注入.这里的解决方案类似于注入问题的解决方案(参数化查询).也就是说,如果你想知道的语句eval是一个非常具体的形式,而不是所有语句都需要由用户提交,只有少数变量,数学表达式或类似的,你可以接受这些来自用户的小块,必要时对它们进行清理,然后使用插入适当位置的用户输入来评估安全模板语句.
小智 11
在Ruby中,有几个噱头可能比eval()以下更合适:
#send一个允许您调用一个名称为字符串并将参数传递给它的方法.yield 允许您将代码块传递给将在接收方法的上下文中执行的方法.Kernel.const_get("String")就足以获得您的名称为字符串的类.我想我无法详细解释它们,所以我只是给了你提示,如果你有兴趣,你会谷歌.
Dom*_*omQ 10
eval不仅不安全(正如其他地方所指出的那样),它也很慢.每次执行时,的AST eval需要编辑代码解析(和如JRuby的,变成字节码),新生活,这是一个字符串,重操作,并且也可能是缓存局部性差(假设正在运行的下程序不是eval很多,因此解释器的相应部分因此是缓存冷,除了很大).
eval你问,为什么在Ruby中根本没有?"因为我们可以"大多数 - 事实上,当eval发明时(对于LISP编程语言),它主要是为了表演!更重要的是,使用eval是正确的事情,当你想"添加一个解释成你的解释",元编程任务,比如写一个预处理器,调试器或一个模板引擎.这类应用的共同想法是按摩一些Ruby代码,并调用eval它,它肯定击败重塑和实施特定于域的玩具语言,一个陷阱也被称为格林斯潘第十定律.需要注意的是:注意成本,例如对于模板引擎,eval在启动时进行所有操作而不是运行时间; 并且不要不eval信任代码,除非你知道如何"驯服"它,即根据能力规则理论选择并强制执行语言的安全子集.后者是很多非常困难的工作(例如,看看Java是如何完成的 ;我不知道Ruby的任何这样的努力).
它使调试变得困难.它使优化变得困难.但最重要的是,这通常表明有更好的方法可以做任何你想做的事情.
如果您告诉我们您要完成的任务eval,您可能会得到一些与您的具体方案相关的更相关的答案.
小智 6
Eval是一个非常强大的功能,应该谨慎使用.除了Matt J指出的安全问题之外,您还会发现调试运行时评估的代码非常困难.解释器难以表达运行时评估的代码块中的问题 - 因此查找它将很困难.
话虽这么说,如果你对这个问题感到满意,并且不关心安全问题,那么你就不应该避免使用使ruby成为吸引人的功能之一.
在某些情况下,良好的位置eval是聪明的,并减少了所需的代码量.除了Matt J提到的安全问题之外,您还需要问自己一个非常简单的问题:
如果一切都说完了,那么其他人是否可以阅读您的代码并了解您的所作所为?
如果答案是否定的,那么你获得的内容eval就会被遗忘以保持可维护性.这个问题不仅适用于您在团队中工作,而且也适用于您 - 您希望能够回顾您的代码月,如果不是几年,也知道您做了什么.
| 归档时间: |
|
| 查看次数: |
6741 次 |
| 最近记录: |