Quando un metodo viene chiamato da un filo con $ SAFE = 4, tale metodo viene eseguito con il livello SAFE stesso $:
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
Tuttavia, quando un blocco viene richiamato, sembra usare il $ SAFE il suo contesto originale invece:
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
Qualcuno può spiegare perché funziona in questo modo? Sembra un problema di sicurezza.
(la ragione per cui sto usando raise
invece di puts
è che puts
non funziona a $ SAFE = 4)
Questo può essere usato a eval una stringa contaminato in un contesto apparentemente sicuro:
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
Una chiusura non acquisisce il valore al momento della definizione? –
Sei in grado di eseguire azioni all'interno del blocco che consentirebbe un livello '$ SAFE' di 0? –
Andrew: si. Sostituire il contenuto del lambda con qualcosa come 'puts \' hostname \ '' fa sì che faccia esattamente quello all'interno del thread $ SAFE = 4. Capisco questo comportamento da una prospettiva di scope (kinda) - Mi chiedo solo se $ SAFE sia completamente rotto a questo riguardo. – rcrogers