2012-03-28 9 views
7

は方法が$ SAFE = 4とのスレッドによって呼び出されると、そのメソッドは、同じ$ SAFEレベルで実行されます。ブロックが呼び出されたときに

def test_method 
    raise "value of $SAFE inside the method: #{$SAFE}" 
end 
t = Thread.new{$SAFE = 4; self.test_method}; t.join 
=> RuntimeError: value of $SAFE inside the method: 4 

しかし、からの$ SAFEを使用しているようです代わりに元のコンテキスト:

test_lambda = lambda do 
    raise "value of $SAFE inside the lambda: #{$SAFE}" 
end 
t = Thread.new{$SAFE = 4; test_lambda.call}; t.join 
=> RuntimeError: value of $SAFE inside the lambda: 0 

誰かがこのように動作する理由を説明できますか?セキュリティ上の問題のようです。

(私が代わりにputsraiseを使用している理由は、putsは$ SAFEで動作しないということである= 4)これは、一見安全なコンテキストで汚染された文字列をevalに使用することができます

test_lambda = lambda{|s| puts "Tainted: #{s.tainted?}"; eval s} 
t = Thread.new{$SAFE = 4; test_lambda.call("puts `date`")}; t.join 
=> Tainted: true 
=> Fri Mar 30 03:15:33 UTC 2012 
+0

クロージャは定義時に値を取得しませんか? –

+1

'$ SAFE'レベルの0で許されるアクションをブロック内で実行できますか? –

+1

Andrew:はい。ラムダの内容を 'puts \' hostname \ ''のようなものに置き換えると、$ SAFE = 4スレッド内のものと同じようになります。私はスコープの観点からこの動作を理解しています(ちょっとしたこと) - これに関しては、$ SAFEが完全に壊れているかどうかは分かりません。 – rcrogers

答えて

5

ラムダはそれがで定義された範囲で動作するためにです(すべてのローカル変数を含む!)そこで

、あなたは安全なレベル0でラムダを定義し、それがゆえ時にそのレベルで実行変数の状態がどうなったかというと、それが呼び出されました。

関連する問題