如何从ruby加载中捕获返回值?

时间:2012-10-21 13:42:10

标签: ruby ruby-on-rails-3

我想为我正在构建的cms加载一个主题..我正在考虑拥有一个名为name_of_theme.themespec的文件..我会加载它...类似于Bundler与gemspecs相同...我在想在这个文件中我会有类似的东西:

Theme.new do |t|
  t.value = 'hi'
end

我想在加载脚本后捕获这个主题实例。我应该抓住文件的内容并评估它们吗?这引出了一个跟进问题,加载文件和阅读内容和评估之间有什么区别..我知道'eval'通常被认为是破坏的预兆...也许这个用例好吗?

关注

根据选定的答案..为什么我得到:

evaluationContext = Fiber.new {$SAFE = 4; Fiber.yield binding}.resume
 => #<Binding:0x007f85fc8a0fc8> 
a = evaluationContext.eval('puts $SAFE')
=> 0

1 个答案:

答案 0 :(得分:3)

嗯,存在一些差异,但如果您已经接受外部代码,那么间距安全漏洞的大小与evalrequire相同。在这种情况下,实际上,eval可能更多安全,因为它可以让您控制代码执行的命名空间和安全级别。这很重要,因为,例如,您的应用处理某人的电子邮件密码。如果让主题在主命名空间(require)中执行,它可以做一些卑鄙的事情,比如重新定义Kernel#gets以将数据记录到恶意服务器等等。虽然听起来很遥远,但最好是安全。这就是你如何做这种类型的安全负载:

evaluationContext = Fiber.new {$SAFE = 4; Fiber.yield binding}.resume
theme = evaluationContext.eval(File.read("GrayTheme.themespec"))

注意:从主题调用的任何代码都将在$ SAFE 4下执行,所以虽然大多数事情都很好(他们不能调用system("rm -rf /")),但是有少量的$ SAFE 0需要从主题中调用的代码,当您仍处于安全级别0时,必须在lambda中创建代码,然后将其传递给安全级别4的代码(因为lambdas保留其安全值)。

编辑:尝试用以下代码替换eval行:

theme = eval(File.read("blahblahba"), evaluationContext)