Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何获取传递给eval方法的块的返回值?_Ruby_Eval_Return Value_Yield - Fatal编程技术网

Ruby 如何获取传递给eval方法的块的返回值?

Ruby 如何获取传递给eval方法的块的返回值?,ruby,eval,return-value,yield,Ruby,Eval,Return Value,Yield,我想实现一些类似沙箱的东西,它可以 求值给定字符串 在与eval相同的上下文中执行给定的块 返回块的结果 沙盒的目的是检查易受攻击代码的内容——函数、变量、e.t.c 这是我的说明书 it 'returns return value of given block' do value = Sandbox.secure_eval('hoge = ["hoge", "fuga"]') do hoge[0] end expect(value).to eq('hoge') end

我想实现一些类似沙箱的东西,它可以

  • 求值给定字符串
  • 在与eval相同的上下文中执行给定的块
  • 返回块的结果
沙盒的目的是检查易受攻击代码的内容——函数、变量、e.t.c

这是我的说明书

it 'returns return value of given block' do
  value = Sandbox.secure_eval('hoge = ["hoge", "fuga"]') do
    hoge[0]
  end
  expect(value).to eq('hoge')
end
这是我的沙盒实现

require 'timeout'
module Sandbox
  def self.secure_eval(code, timeout: 5, safe_level: 2)
    raise ArgumentError, 'please set call back by block' unless block_given?

    proc = Proc.new do
      Timeout::timeout timeout do
        $SAFE = safe_level
        eval code do
          yield
        end
      end
    end

    proc.call
  end
end
但是#secure_eval返回eval的结果,在本例中为[“hoge”,“fuga”],无法捕获块的返回值

require 'timeout'

module Sandbox
  refine Binding do
    def method_missing(meth, *args, &block)
      self.eval(meth.to_s)
    end
  end

  def self.secure_eval(code, timeout: 5, safe_level: 2, &block)
    raise ArgumentError, 'please set call back by block' unless block_given?

    proc = Proc.new do
      Timeout::timeout timeout do
        $SAFE = safe_level
        binding = binding()
        binding.eval(code)
        binding.instance_eval(&block)
      end
    end

    proc.call
  end
end

using Sandbox # Activate the refinement so we can use x, y, z directly
Sandbox.secure_eval('x = [1,2,3]; y = 0; z = { key: "Hello!" }') do
   x[1]    # => 2
   y       # => 0
   z[:key] # => "Hello!"
end

我该怎么做?

您可以使用
yield
将评估结果返回到块中。您只需
产生
值;因此,我将您的
yield
更改为
yield eval code
。在你给沙盒的块中,你必须将这个结果绑定到一个块变量。
secure\u eval
的结果将是块的结果,如您所愿

proc = Proc.new do
  Timeout::timeout timeout do
    $SAFE = safe_level
    yield eval code # <= This line changed
  end
end

Sandbox.secure_eval('hoge = ["hoge", "fuga"]') { |hoge| hoge[0] }
# => "hoge"

Sandbox.secure_eval('2 ** 4') { |result| result - 5 }
# => 11

您可以使用
yield
将eval结果返回到块。您只需
产生
值;因此,我将您的
yield
更改为
yield eval code
。在你给沙盒的块中,你必须将这个结果绑定到一个块变量。
secure\u eval
的结果将是块的结果,如您所愿

proc = Proc.new do
  Timeout::timeout timeout do
    $SAFE = safe_level
    yield eval code # <= This line changed
  end
end

Sandbox.secure_eval('hoge = ["hoge", "fuga"]') { |hoge| hoge[0] }
# => "hoge"

Sandbox.secure_eval('2 ** 4') { |result| result - 5 }
# => 11

我不认为块在任何地方都可以调用-
eval
不接受块…引述如下:“然而,
$SAFE
并没有为执行不受信任的代码提供一个安全的环境。”您永远不应该依赖Ruby内置的
$SAFE
或任何其他通用的“安全代码执行”机制(或大多数其他语言)在执行不受信任(以及潜在的恶意)代码时保护您免受伤害。你的沙箱根本不是沙箱!我不认为块在任何地方都可以调用-
eval
不接受块…引述如下:“然而,
$SAFE
并没有为执行不受信任的代码提供一个安全的环境。”您永远不应该依赖Ruby内置的
$SAFE
或任何其他通用的“安全代码执行”机制(或大多数其他语言)在执行不受信任(以及潜在的恶意)代码时保护您免受伤害。你的沙箱根本不是沙箱!谢谢你的回复。您的代码似乎正常工作,但我希望我的沙盒可以像下面那样工作:sandbox.secure_eval('hoge=[“hoge”,“fuga”];piyo=“piyo”'){hoge[0]}#=>“hoge”有什么办法吗?@Mekajiki Ah所以您希望能够访问您在
eval
中声明的任何变量。。我不知道这是否可行,
eval
只返回最后一个表达式的值,而不返回中间表达式的值。也许这是可能的,但我不知道一种方法。@Mekajiki我已经用一种方法更新了我的帖子,可以访问其他定义的变量。你必须在
绑定中添加
*args
block
eval
,但是对block这样做一点都不简单。@hakcho我添加了改进的用法,现在需要
使用沙盒
来启用补丁绑定行为,而不是全局启用。感谢您的回复。您的代码似乎正常工作,但我希望我的沙盒可以像下面那样工作:sandbox.secure_eval('hoge=[“hoge”,“fuga”];piyo=“piyo”'){hoge[0]}#=>“hoge”有什么办法吗?@Mekajiki Ah所以您希望能够访问您在
eval
中声明的任何变量。。我不知道这是否可行,
eval
只返回最后一个表达式的值,而不返回中间表达式的值。也许这是可能的,但我不知道一种方法。@Mekajiki我已经用一种方法更新了我的帖子,可以访问其他定义的变量。你必须在
绑定中添加
*args
block
eval
,但是对block这样做一点都不简单。@hakcho我添加了改进的用法,现在需要
使用Sandbox
来启用补丁绑定行为,而不是全局启用。