$SAFE is Proc-local

| 1 Comment

While researching Ruby's new-in-1.9 Object methods untrusted?, untrust, and trust, I discovered something I did not know about the $SAFE variable: in addition to being Thread-local, it is also Proc-local. Proc objects (both procs and lambdas) have their own copy of $SAFE, and they run at whatever $SAFE level was in effect when the Proc was created not the safe level that is in effect when they are invoked. This was discussed three years ago over at _why's old blog.

There is a corollary, however that was demonstrated but not discussed in a recent ruby-core post by Shugo Maeda: if you set $SAFE inside a proc or a lambda, that setting is local, and does not change the global safe level. Googling for "safe_eval" implementations shows that everyone uses Thread.new to create a sandbox with a locally elevated safe level. It turns out, however, that an ordinary lambda will also work. (One can argue, however, that a thread gives extra safety because it can be monitored and killed to guard against runaway code that doesn't terminate.)

In any case, here is the method I defined to try this out. Pass it a safe level (it defaults to 4) and a block of code, and it will execute the block at that level without altering the global safe level and without creating a new thread:

# Execute a block at the specified safe level. Tested with Ruby 1.9 and 1.8.7
def safely(level = 4)
  sandbox = lambda do # Set up a sandbox 
    $SAFE = level     # Go to the specified safe level for this lambda only
    yield             # Invoke the block at that level
  end
  sandbox.call        # Invoke the sandbox without changing $SAFE globally
end

# Use this method like this. 
x = safely { eval('"untrusted code"') }
[x, x.tainted?, x.untrusted?]  # => ["untrusted code", true, true]

I'm not convinced that this method is actually useful in practice, but I thought it was interesting, and it reminds me again how cool it is to be able to define methods that accept blocks and act like control statements.

1 Comment


Hi David,

really interested in seeing the code for this old post if possible please : http://www.davidflanagan.com/2005/08/canvas-tag-in-java-and-xbl.html

I'm investigating renderering canvas tags on the serverside to images.

cheers
Colin

Leave a comment

Books

Comprehensive coverage of Ruby 1.8 and 1.9

"The New Most Important Ruby Book"
Peter Cooper,
rubyinside.com

Completely updated for Ajax and Web 2.0

"A must-have reference"
Brendan Eich,
creator of JavaScript

The classic Java quick-reference

Advertising

Pages

Hosted By

Powered by Movable Type 4.21-en