2012-03-28 9 views
7

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 
+0

Una chiusura non acquisisce il valore al momento della definizione? –

+1

Sei in grado di eseguire azioni all'interno del blocco che consentirebbe un livello '$ SAFE' di 0? –

+1

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

risposta

5

è perché un lambda opera con lo scopo è stato definito in (tra cui tutte le variabili locali!)

quindi, è stato definito il lambda a livello di sicurezza 0, e quindi giustiziato a quel livello, quando è stato chiamato, poiché era lo stato della variabile.

Problemi correlati