hoodwink.d enhanced
RSS
2.0
XHTML
1.0

RedHanded

Lambda is a $SAFEcracker #

by why in inspect

MenTaL sends this one in:

 pr = lambda { puts "Safelevel: #$SAFE" }
 $SAFE = 4
 pr.call
 1.times(&pr)

Bug or feature? Anyone want to help us out here? Globals are thread-local, so it’s not the case with other globals. So what makes $SAFE so special? (Seen on ~sasada.)

said on 27 Jul 2005 at 09:56

More intriguing, why does it work via Proc#call, but never when passing a block (even after it’s been lambda-ized)?

said on 27 Jul 2005 at 10:02

Isn’t this related to the lambda being created before setting $SAFE? Regarding the block use: I guess that could be related to instance_eval(&pr).

said on 27 Jul 2005 at 10:30

flgr: That’s the point—the lambda seems to capture the current value of $SAFE as part of its environment.

Though, only if you call it via Proc#call object—not if you yield to it. Which is the weird thing.

Could you elaborate on the instance_eval thing? Fixnum#times just yields.

said on 27 Jul 2005 at 10:36

the feature. the code wrapped in the lambda is trusted in the level of $SAFE at the time of creation, so that it preserves $SAFE level. If you have found a hole in my logic, enlighten me, please.

said on 27 Jul 2005 at 10:43

Hi matz. That seems reasonable.

However, why does yield ignore saved $SAFE level?

said on 27 Jul 2005 at 11:16

two reasons: a) yield sometimes tweak the environment (e.g. self) so that the execution might not be safe anymore. b) it is far more difficult to make it work properly (even if there could be a proper behavior) by the implementation issue.

said on 27 Jul 2005 at 11:23

Good answers. Thankyou, Matz.

I like this. It’s a great way of straddling two or more security levels at once without needling to split threads.

Wondering. Are there Railsers who use $SAFE?

said on 27 Jul 2005 at 11:40

I have an IRC bot that allows users to update modules and channel protection code. I trust them to admin my channel, but not to run arbitrary code on my computer.

$SAFE lets me run their code with a relative degree of safety.

said on 27 Jul 2005 at 11:45

I am least surprised that Continuation also captures $SAFE:


cont = nil
ret = callcc { |cont| nil }
if ret
  p $SAFE
  ret.call
end

$SAFE = 4

callcc &cont.method(:call)
said on 27 Jul 2005 at 11:59

I have tried it in the past and Rails got really mad at me.

Comments are closed for this entry.