Wenn ein Verfahren durch ein Gewinde mit $ SAFE = 4, das Verfahren ausgeführt wird mit dem gleichen $ sicheren Niveau genannt:
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
Wenn jedoch ein Block genannt wird, ist es den $ sicher zu verwenden scheint aus der ursprüngliche Kontext stattdessen:
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
Kann jemand erklären, warum es so funktioniert? Es scheint ein Sicherheitsproblem zu sein.
(der Grund, warum ich raise
statt puts
bin ist, dass puts
nicht bei $ SAFE funktioniert = 4)
Dies kann eine verdorbene Zeichenfolge eval in einem scheinbar sicheren Kontext verwendet werden:
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
Würde eine Schließung den Wert zum Zeitpunkt der Definition nicht erfassen? –
Können Sie Aktionen innerhalb des Blocks ausführen, die ein '$ SAFE' Level von 0 erlauben würde? –
Andrew: Ja. Ersetzen Sie den Inhalt des Lambda durch etwas wie 'puts \' hostname \ '' verursacht es genau das aus dem $ SAFE = 4 Thread. Ich verstehe dieses Verhalten aus einer Perspektive (irgendwie) - Ich frage mich nur, ob $ SAFE in dieser Hinsicht völlig gebrochen ist. – rcrogers