Once $SAFE is set to a certain level, it’s not possible to lower it again. As
far as I know, the only way to execute some code at a high $SAFE level and
then return to a lower one is like this:
module Kernel
def safe(level, &block)
thread = Thread.new {
$SAFE = 4
block.call
}
thread.join
end
end
p Thread.current.safe_level
safe(4) { p Thread.current.safe_level }
batsman@tux-chan:/tmp$ ruby b.rb
0
b.rb:13:in write': Insecure operation write’ at level 4
(SecurityError)
from b.rb:8:in join' from b.rb:8:in safe’
from b.rb:13
···
On Wed, Dec 18, 2002 at 06:59:21PM +0900, Tim Bates wrote:
Once $SAFE is set to a certain level, it’s not possible to lower it again. As
far as I know, the only way to execute some code at a high $SAFE level and
then return to a lower one is like this:
thread = Thread.new {
$SAFE = 4
… do code
}
thread.join
Which is messy to say the least. Why not have something like:
Kernel#safe(anInteger) { block }
Or even:
Kernel#eval_safe(aString, anInteger)
Although this could probably be written in terms of the first one.
Is there something like this already? If not, why not?
Once $SAFE is set to a certain level, it’s not possible to lower it again. As
far as I know, the only way to execute some code at a high $SAFE level and
then return to a lower one is like this:
thread = Thread.new {
$SAFE = 4
… do code
}
thread.join
Which is messy to say the least. Why not have something like:
Kernel#safe(anInteger) { block }
module Kernel
def safe(level)
proc {$SAFE = level; yield}.call
end
end
p Thread.current.safe_level # => 0
p safe(4) { Thread.current.safe_level } # => 4
p Thread.current.safe_level # => 0
···
At Wed, 18 Dec 2002 18:59:21 +0900, Tim Bates wrote:
Much better! It doesn’t use more threads, which is what I was looking for. I
didn’t realise Proc reset $SAFE at its end. Thanks a lot. And thanks to the
person who submitted the other solution, even if it wasn’t what I wanted.
At Wed, 18 Dec 2002 19:48:49 +0900, Tim Bates wrote:
module Kernel
def safe(level)
proc {$SAFE = level; yield}.call
end
end
p Thread.current.safe_level # => 0
p safe(4) { Thread.current.safe_level } # => 4
p Thread.current.safe_level # => 0
Much better! It doesn’t use more threads, which is what I was looking for. I
didn’t realise Proc reset $SAFE at its end. Thanks a lot. And thanks to the
person who submitted the other solution, even if it wasn’t what I wanted.
Proc doesn’t reset $SAFE, but has each own safe level.
This behavior was pointed out by nagai@ai.kyutech.ac.jp at
[ruby-dev:17220], and admitted as feature.