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
Czy zamknięcie nie może uchwycić wartości w momencie definicji? –
Czy jesteś w stanie wykonać działania w ramach bloku, które pozwoliłoby na poziom '$ SAFE' równy 0? –
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