2012-03-28 11 views
7

Gdy metoda jest wywoływana przez wątek dolarów safe = 4, że metoda jest prowadzony z tego samego $ bezpiecznym poziomie:

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 

Jednak, gdy blok nazywa, wydaje się użyć $ bezpieczny od zamiast tego oryginalny kontekst:

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 

Czy ktoś może wyjaśnić, dlaczego działa w ten sposób? Wydaje się, że jest to problem związany z bezpieczeństwem.

(powód używam raise zamiast puts że puts nie działa w $ SAFE = 4)

ten może być stosowany do eval złośliwej ciąg w pozornie bezpiecznym kontekście:

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

Czy zamknięcie nie może uchwycić wartości w momencie definicji? –

+1

Czy jesteś w stanie wykonać działania w ramach bloku, które pozwoliłoby na poziom '$ SAFE' równy 0? –

+1

Andrew: tak. Zastąpienie zawartości lambda czymś takim jak 'puts \ nazwa_hosta \' 'powoduje, że robi to dokładnie z wątku $ SAFE = 4. Rozumiem to zachowanie z perspektywy zakresu (rodzaj) - Zastanawiam się tylko, czy $ SAFE jest całkowicie zepsute w tym zakresie. – rcrogers

Odpowiedz

5

to dlatego lambda pracuje z zakresu że została zdefiniowana w (w tym wszystkie zmienne lokalne!)

Stąd zdefiniowano lambda na bezpiecznym poziomie 0, a to dlatego wykonywane na tym poziomie, gdy zostało to nazwane, ponieważ taki był stan zmiennej.

Powiązane problemy