$SAFE block?

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?

Tim Bates

···


tim@bates.id.au

You can write it yourself:

batsman@tux-chan:/tmp$ cat b.rb

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?


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Never trust an operating system you don’t have sources for. :wink:
– Unknown source

Hi,

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:


Nobu Nakada

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.

Tim Bates

···

On Wed, 18 Dec 2002 09:14 pm, nobu.nokada@softhome.net 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


tim@bates.id.au

Hi,

···

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.


Nobu Nakada