2012-03-28 29 views
7

Khi một phương pháp được gọi bằng một sợi với $ AN TOÀN = 4, phương pháp mà được chạy với cùng $ mức AN TOÀN:

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 

Tuy nhiên, khi một khối được gọi là, có vẻ như sử dụng $ AN TOÀN từ bối cảnh ban đầu của nó thay vào đó:

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 

Ai đó có thể giải thích tại sao nó hoạt động theo cách này? Nó có vẻ như một vấn đề an ninh.

(lý do tôi đang sử dụng raise thay vì putsputs không hoạt động tại $ AN TOÀN = 4)

này có thể được sử dụng để eval một chuỗi nhiễm độc trong bối cảnh dường như an toàn:

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

Sẽ không đóng cửa ghi lại giá trị tại thời điểm xác định? –

+1

Bạn có thể thực hiện các hành động trong khối mà mức '$ SAFE' bằng 0 sẽ cho phép không? –

+1

Andrew: có. Thay thế nội dung của lambda bằng một cái gì đó như 'puts \' hostname \ '' làm cho nó làm chính xác từ bên trong $ SAFE = 4 thread. Tôi hiểu hành vi này từ một phối cảnh phạm vi (kinda) - Tôi chỉ tự hỏi liệu SAFE $ có bị hỏng hoàn toàn trong vấn đề này hay không. – rcrogers

Trả lời

5

đó là bởi vì một lambda hoạt động với phạm vi được quy định tại (bao gồm tất cả các biến địa phương!)

do đó, bạn xác định lambda ở mức an toàn 0, và do đó nó được thực hiện ở cấp độ đó khi nó được gọi, vì đó là trạng thái của biến.

Các vấn đề liên quan