# Binding.of\_caller examples don't work

**URL:** <https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088>\
**Category:** ruby-talk\
**Created:** [10 January 2009 20:49 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088 "2009-01-10T20:49:50Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Doug](https://avatars.discourse-cdn.com/v4/letter/d/dbc845/32.png) [@Doug](https://rubytalk.org/u/Doug)\
**Post date:** [10 January 2009 20:49 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/1 "2009-01-10T20:49:50Z")

</div>

I'm trying to use the Binding class in the extensions library  
[http://extensions.rubyforge.org/rdoc/index.html](http://extensions.rubyforge.org/rdoc/index.html)

In particular, I want the method of\_caller, but none of the examples  
work for me  
get 'undefined method or variable' for all that should be in the  
caller's scope.

local\_variable returns an empty array.

Is this broken?  
...using Ruby 1.8.6

thanks,  
-doug.

---

<div class="post-metadata">

**Author:** ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)\
**Post date:** [11 January 2009 01:55 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/2 "2009-01-11T01:55:57Z")

</div>

Binding.of\_caller is no longer possible.

T.

> **···**
>
> On Jan 10, 3:49 pm, Doug \<dou...@pacbell.net\> wrote:
> 
> > I'm trying to use the Binding class in the extensions libraryhttp://extensions.rubyforge.org/rdoc/index.html
> > 
> > In particular, I want the method of\_caller, but none of the examples  
> > work for me  
> > get 'undefined method or variable' for all that should be in the  
> > caller's scope.
> > 
> > local\_variable returns an empty array.
> > 
> > Is this broken?  
> > ...using Ruby 1.8.6

---

<div class="post-metadata">

**Author:** ![Phlip1](https://avatars.discourse-cdn.com/v4/letter/p/df788c/32.png) [@Phlip1](https://rubytalk.org/u/Phlip1)\
**Post date:** [11 January 2009 02:59 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/3 "2009-01-11T02:59:31Z")

</div>

Trans wrote:

> Binding.of\_caller is no longer possible.

I just thought of a use for it!

Is a workaround available?

---

<div class="post-metadata">

**Author:** ![Pit\_Capitain](https://avatars.discourse-cdn.com/v4/letter/p/d78d45/32.png) [@Pit\_Capitain](https://rubytalk.org/u/Pit_Capitain)\
**Post date:** [11 January 2009 18:11 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/4 "2009-01-11T18:11:30Z")

</div>

It seems that the original idea of Florian Groß is still valid. Here's  
a version working for my Ruby 1.8.6 on Windows:

> **···**
>
> 2009/1/11 Phlip \<phlip2005@gmail.com\>:
> 
> > Trans wrote:
> > 
> > > Binding.of\_caller is no longer possible.
> > 
> > Is a workaround available?
> 
> &nbsp;&nbsp;##  
> &nbsp;&nbsp;# Re-implementation of Binding.of\_caller for Ruby 1.8.6  
> &nbsp;&nbsp;# (C) 2009 Pit Capitain  
> &nbsp;&nbsp;# Original idea and implementation by Florian Gross  
> &nbsp;&nbsp;#  
> &nbsp;&nbsp;def Binding.of\_caller
> 
> &nbsp;&nbsp;&nbsp;&nbsp;old\_critical = Thread.critical  
> &nbsp;&nbsp;&nbsp;&nbsp;Thread.critical = true
> 
> &nbsp;&nbsp;&nbsp;&nbsp;restart\_cc = result = error = nil
> 
> &nbsp;&nbsp;&nbsp;&nbsp;expected\_events = %w"line c-call c-return return return"  
> &nbsp;&nbsp;&nbsp;&nbsp;tracer = lambda do |event, file, line, id, binding, classname|  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if expected\_events.empty?  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set\_trace\_func(nil)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result = binding  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;restart\_cc.call  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elsif event != expected\_events.shift  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set\_trace\_func(nil)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;error =  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"Binding.of\_caller used in non-method context" +  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" or trailing statements of method using it aren't in the block."  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;restart\_cc.call  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;&nbsp;&nbsp;callcc { |cc| restart\_cc = cc }
> 
> &nbsp;&nbsp;&nbsp;&nbsp;if result  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;yield(result)  
> &nbsp;&nbsp;&nbsp;&nbsp;elsif error  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise(ArgumentError, error)  
> &nbsp;&nbsp;&nbsp;&nbsp;else  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;set\_trace\_func(tracer)  
> &nbsp;&nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;ensure  
> &nbsp;&nbsp;&nbsp;&nbsp;Thread.critical = old\_critical  
> &nbsp;&nbsp;end
> 
> Regards,  
> Pit

---

<div class="post-metadata">

**Author:** ![7rans](https://avatars.discourse-cdn.com/v4/letter/7/a8b319/32.png) [@7rans](https://rubytalk.org/u/7rans)\
**Post date:** [11 January 2009 19:13 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/5 "2009-01-11T19:13:29Z")

</div>

Cool. But word or warning to Doug, I would not recommend using  
#set\_trace\_func in a production application. It can slow things down  
considerably.

T.

> **···**
>
> On Jan 11, 1:11 pm, "Pit Capitain" \<pit.capit...@gmail.com\> wrote:
> 
> > 2009/1/11 Phlip \<phlip2...@gmail.com\>:
> > 
> > \> Trans wrote:  
> > \>\> Binding.of\_caller is no longer possible.
> > 
> > \> Is a workaround available?
> > 
> > It seems that the original idea of Florian Groß is still valid. Here's  
> > a version working for my Ruby 1.8.6 on Windows:
> > 
> > ##  
> > # Re-implementation of Binding.of\_caller for Ruby 1.8.6  
> > # (C) 2009 Pit Capitain  
> > # Original idea and implementation by Florian Gross  
> > #  
> > def Binding.of\_caller
> > 
> > ```
> > old\_critical = Thread\.critical
> > Thread\.critical = true
> > 
> > restart\_cc = result = error = nil
> > 
> > expected\_events = %w&quot;line c\-call c\-return return return&quot;
> > tracer = lambda do |event, file, line, id, binding, classname|
> > if expected\_events\.empty?
> > set\_trace\_func\(nil\)
> > result = binding
> > restart\_cc\.call
> > elsif event \!= expected\_events\.shift
> > set\_trace\_func\(nil\)
> > error =
> > &quot;Binding\.of\_caller used in non\-method context&quot; \+
> > &quot; or trailing statements of method using it aren&#39;t in the block\.&quot;
> > restart\_cc\.call
> > end
> > end
> > 
> > callcc \{ |cc| restart\_cc = cc \}
> > 
> > if result
> > yield\(result\)
> > elsif error
> > raise\(ArgumentError, error\)
> > else
> > set\_trace\_func\(tracer\)
> > end
> > 
> > ```
> > 
> > ensure  
> > Thread.critical = old\_critical  
> > end

---

<div class="post-metadata">

**Author:** ![Ken\_Bloom](https://avatars.discourse-cdn.com/v4/letter/k/f08c70/32.png) [@Ken\_Bloom](https://rubytalk.org/u/Ken_Bloom)\
**Post date:** [12 January 2009 02:39 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/6 "2009-01-12T02:39:24Z")

</div>

First, the version in the extensions gem uses Florian Groß's idea, so  
it's the same as what Philip posted, modulo the organization of  
initialization code and the like.

Second, the trace function is only being used for a couple of calls  
before the continuation is called, and execution jumps back into  
Binding.of\_caller at which point the trace function is removed. It  
wouldn't appear to me like it would hurt things too much. (Maybe it  
requires turning on an otherwise disabled feature in JRuby?)

Third: it looks like this should be portable to Ruby 1.9. Ruby 1.9 no  
longer has Thread.critical, replacing it with Thread.exclusive (which  
takes a block). Although Thread.exclusive is not suitable for this  
function because the block exits before the function exits, it should be  
unnecessary to lock out other threads anymore, since you should be able  
to do a Thread.current.set\_trace\_func instead of Kernel#set\_trace\_func  
and have it affect only the current thread.

--Ken

> **···**
>
> On Sun, 11 Jan 2009 14:13:29 -0500, Trans wrote:
> 
> > On Jan 11, 1:11 pm, "Pit Capitain" \<pit.capit...@gmail.com\> wrote:
> > 
> > > 2009/1/11 Phlip \<phlip2...@gmail.com\>:
> > > 
> > > \> Trans wrote:  
> > > \>\> Binding.of\_caller is no longer possible.
> > > 
> > > \> Is a workaround available?
> > > 
> > > It seems that the original idea of Florian Groß is still valid.
> > 
> > Cool. But word or warning to Doug, I would not recommend using  
> > #set\_trace\_func in a production application. It can slow things down  
> > considerably.
> > 
> > T.
> 
> --  
> Chanoch (Ken) Bloom. PhD candidate. Linguistic Cognition Laboratory.  
> Department of Computer Science. Illinois Institute of Technology.  
> [http://www.iit.edu/~kbloom1/](http://www.iit.edu/~kbloom1/)

---

<div class="post-metadata">

**Author:** ![Charles\_Oliver\_Nutte](https://avatars.discourse-cdn.com/v4/letter/c/71e660/32.png) [@Charles\_Oliver\_Nutte](https://rubytalk.org/u/Charles_Oliver_Nutte)\
**Post date:** [12 January 2009 03:27 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/7 "2009-01-12T03:27:29Z")

</div>

Ken Bloom wrote:

> Second, the trace function is only being used for a couple of calls before the continuation is called, and execution jumps back into Binding.of\_caller at which point the trace function is removed. It wouldn't appear to me like it would hurt things too much. (Maybe it requires turning on an otherwise disabled feature in JRuby?)

Tracing works, but JRuby and IronRuby do not support continuations, and I think they work differently in 1.9. It's a hack that's unlikely to work reliably, even across minor versions of a given implementation.

In general I think Binding.of\_caller is a really, really bad idea because it exposes internal details every method call in \*your\* code to the whims of \*someone else's\* code. Basically, it breaks the most sacred encapsulation possible, a method call's local variables.

Imagine a case like this:

def secure\_action(encrypted\_password)  
&nbsp;&nbsp;&nbsp;decrypted\_password = decrypt(encrypted\_password)  
&nbsp;&nbsp;&nbsp;authorize(decrypted\_password)  
&nbsp;&nbsp;&nbsp;do\_secure\_task  
end

If it were possible to modify do\_secure task, or if you were simply calling a third-party library, it could access the runtime variables of the caller:

def do\_secure\_task  
&nbsp;&nbsp;&nbsp;binding = Binding.of\_caller  
&nbsp;&nbsp;&nbsp;vars = eval 'local\_variables', binding  
&nbsp;&nbsp;&nbsp;vars.each do |name|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if name =~ /password/  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;use\_for\_evil(eval name, binding)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end  
end

I even implemented Binding.of\_caller for fun once in JRuby, and removed it when I realized how invasive and dangerous it was.

Just like retry was limited in 1.9 to restarting a rescued block of code (rather than being able to reevaluate the original arguments and receiver), Binding.of\_caller should remain unsupported.

- Charlie

---

<div class="post-metadata">

**Author:** ![Bill\_Kelly](https://avatars.discourse-cdn.com/v4/letter/b/cc9497/32.png) [@Bill\_Kelly](https://rubytalk.org/u/Bill_Kelly)\
**Post date:** [12 January 2009 09:10 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/8 "2009-01-12T09:10:56Z")

</div>

> In general I think Binding.of\_caller is a really, really bad idea because it exposes internal details every method call in \*your\* code to the whims of \*someone else's\* code. Basically, it breaks the most sacred encapsulation possible, a method call's local variables.
> 
> Imagine a case like this:
> 
> def secure\_action(encrypted\_password)  
> &nbsp;&nbsp;decrypted\_password = decrypt(encrypted\_password)  
> &nbsp;&nbsp;authorize(decrypted\_password)  
> &nbsp;&nbsp;do\_secure\_task  
> end
> 
> If it were possible to modify do\_secure task, or if you were simply calling a third-party library, it could access the runtime variables of the caller:
> 
> def do\_secure\_task  
> &nbsp;&nbsp;binding = Binding.of\_caller  
> &nbsp;&nbsp;vars = eval 'local\_variables', binding  
> &nbsp;&nbsp;vars.each do |name|  
> &nbsp;&nbsp;&nbsp;&nbsp;if name =~ /password/  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;use\_for\_evil(eval name, binding)  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end  
> end

If we're calling untrusted code and giving it full execution privileges, then  
I think Binding.of\_caller is the least of our worries. The untrusted code  
could as easily `rm -rf ~` or innumerable other evil things.

Untrusted code needs to be sandboxed.

Seems we could either make Binding.of\_caller not work at all if $SAFE  
is \>= 3 ... or preferably, if it's possible for the interpreter to determine  
whether the caller's binding would have a lower $SAFE level than the  
current binding, then only raise a SecurityException in that case.

Would this address your security concerns?

Regards,

Bill

> **···**
>
> From: "Charles Oliver Nutter" \<charles.nutter@sun.com\>

---

<div class="post-metadata">

**Author:** ![Ken\_Bloom](https://avatars.discourse-cdn.com/v4/letter/k/f08c70/32.png) [@Ken\_Bloom](https://rubytalk.org/u/Ken_Bloom)\
**Post date:** [12 January 2009 15:09 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/9 "2009-01-12T15:09:28Z")

</div>

It turns out that Binding.of\_caller isn't a hack I need. It's a hack I  
though I needed when I thought I'd have to use Ripper to fix s-expression  
generation in the SqlStatement for Ruby 1.9. Then I discovered that all  
the operators I needed were now overloadable, so I went with that instead.

Which reminds me of another question I had. You were discussing somewhere  
else how Thread.critical works in JRuby. Does Thread.critical /  
Thread.exclusive in JRuby protect other threads against changes to the  
core class methods? Can I run Thread.critical=true , dramatically  
redefine operators on the core classes, redefine the operators back  
their original implementations, run Thread.critical=false, and expect  
that no other JRuby thread can get in and be broken becuase I've  
dramatically gutted the core classes?

> **···**
>
> On Sun, 11 Jan 2009 22:27:29 -0500, Charles Oliver Nutter wrote:
> 
> > Ken Bloom wrote:
> > 
> > > Second, the trace function is only being used for a couple of calls  
> > > before the continuation is called, and execution jumps back into  
> > > Binding.of\_caller at which point the trace function is removed. It  
> > > wouldn't appear to me like it would hurt things too much. (Maybe it  
> > > requires turning on an otherwise disabled feature in JRuby?)
> > 
> > Tracing works, but JRuby and IronRuby do not support continuations, and  
> > I think they work differently in 1.9. It's a hack that's unlikely to  
> > work reliably, even across minor versions of a given implementation.
> > 
> > In general I think Binding.of\_caller is a really, really bad idea  
> > because it exposes internal details every method call in \*your\* code to  
> > the whims of \*someone else's\* code. Basically, it breaks the most sacred  
> > encapsulation possible, a method call's local variables.
> > 
> > Imagine a case like this:
> > 
> > def secure\_action(encrypted\_password)  
> > &nbsp;&nbsp;&nbsp;decrypted\_password = decrypt(encrypted\_password)  
> > &nbsp;&nbsp;&nbsp;authorize(decrypted\_password)  
> > &nbsp;&nbsp;&nbsp;do\_secure\_task  
> > end
> > 
> > If it were possible to modify do\_secure task, or if you were simply  
> > calling a third-party library, it could access the runtime variables of  
> > the caller:
> > 
> > def do\_secure\_task  
> > &nbsp;&nbsp;&nbsp;binding = Binding.of\_caller  
> > &nbsp;&nbsp;&nbsp;vars = eval 'local\_variables', binding vars.each do |name|  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if name =~ /password/  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;use\_for\_evil(eval name, binding)  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;end  
> > end
> > 
> > I even implemented Binding.of\_caller for fun once in JRuby, and removed  
> > it when I realized how invasive and dangerous it was.
> > 
> > Just like retry was limited in 1.9 to restarting a rescued block of code  
> > (rather than being able to reevaluate the original arguments and  
> > receiver), Binding.of\_caller should remain unsupported.
> > 
> > - Charlie
> 
> --  
> Chanoch (Ken) Bloom. PhD candidate. Linguistic Cognition Laboratory.  
> Department of Computer Science. Illinois Institute of Technology.  
> [http://www.iit.edu/~kbloom1/](http://www.iit.edu/~kbloom1/)

---

<div class="post-metadata">

**Author:** ![Charles\_Oliver\_Nutte](https://avatars.discourse-cdn.com/v4/letter/c/71e660/32.png) [@Charles\_Oliver\_Nutte](https://rubytalk.org/u/Charles_Oliver_Nutte)\
**Post date:** [12 January 2009 15:21 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/10 "2009-01-12T15:21:24Z")

</div>

Bill Kelly wrote:

> If we're calling untrusted code and giving it full execution privileges, then  
> I think Binding.of\_caller is the least of our worries. The untrusted code  
> could as easily `rm -rf ~` or innumerable other evil things.
> 
> Untrusted code needs to be sandboxed.

Sandboxing is made nearly impossible if calls in your own chain can escalate privileges by executing code from your binding. This is the primary reason why prototype continuation support for the JVM probably will never be shipped...the ability to implicitly access things elsewhere in the call stack has all sorts of really nasty security issues, even in a pretty secure environment like the JVM.

> Seems we could either make Binding.of\_caller not work at all if $SAFE  
> is \>= 3 ... or preferably, if it's possible for the interpreter to determine  
> whether the caller's binding would have a lower $SAFE level than the  
> current binding, then only raise a SecurityException in that case.
> 
> Would this address your security concerns?

No, because JRuby doesn't support $SAFE. It's a blunt instrument that I don't think anyone has ever audited for actual safety. So as a result, anyone believing $SAFE is actually safe is probably introducing even more risk into their apps.

Also, $SAFE is a global thing, and you can't localize it to a given binding, so that wouldn't work anyway.

Honestly, if you want a binding, pass one in.

- Charlie

---

<div class="post-metadata">

**Author:** ![Charles\_Oliver\_Nutte](https://avatars.discourse-cdn.com/v4/letter/c/71e660/32.png) [@Charles\_Oliver\_Nutte](https://rubytalk.org/u/Charles_Oliver_Nutte)\
**Post date:** [12 January 2009 15:34 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/11 "2009-01-12T15:34:26Z")

</div>

Ken Bloom wrote:

> Which reminds me of another question I had. You were discussing somewhere else how Thread.critical works in JRuby. Does Thread.critical / Thread.exclusive in JRuby protect other threads against changes to the core class methods? Can I run Thread.critical=true , dramatically redefine operators on the core classes, redefine the operators back their original implementations, run Thread.critical=false, and expect that no other JRuby thread can get in and be broken becuase I've dramatically gutted the core classes?

You could up until about a week ago, when I proactively modified critical= to just be a reentrant global lock. So basically..

Before:  
\* critical= causes the current thread to be the only thread running  
\* ...except on JRuby where threads run in parallel and have to reach a checkpoint before they stop  
\* ...or if code you call from within a critical section itself spins up threads

After:

\* critical= acquires or releases a lock on a global mutex  
\* threads that don't have critical sections continue running  
\* threads that try to acquire the lock while another thread has it block

This was actually proposed by Shri Borde of IronRuby and blogged here:

> **[Shri Borde's WebLog](https://learn.microsoft.com/en-us/archive/blogs/shrib/)**

She (he?) proposes that almost all current uses of critical= intend to simply delimit a critical section of code, and so a single global mutex is sufficient for those cases. And in light of the fact that native calls and parallel-threaded impls can't be guaranteed to deschedule other threads, I think this is a much more concrete and reasonable definition. So I agreed, said so on a critical-related ruby-core thread, and went ahead with the change. Nothing has broken so far 🙂

For your case, I think your best bet is to either make those changes before other threads start running or just accept that some of them won't see your changes all at once. I believe what you want to do may work on MRI, since it doesn't actually run threads in parallel and critical= stops it from scheduling new ones on its own.

But also note that critical= is gone in 1.9, so you should not use it anyway. Use a Mutex whenever possible...it's quick, easy, and safe.

- Charlie

---

<div class="post-metadata">

**Author:** ![Ken\_Bloom](https://avatars.discourse-cdn.com/v4/letter/k/f08c70/32.png) [@Ken\_Bloom](https://rubytalk.org/u/Ken_Bloom)\
**Post date:** [12 January 2009 17:09 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/12 "2009-01-12T17:09:35Z")

</div>

> Ken Bloom wrote:
> 
> > Which reminds me of another question I had. You were discussing  
> > somewhere else how Thread.critical works in JRuby. Does Thread.critical  
> > / Thread.exclusive in JRuby protect other threads against changes to  
> > the core class methods? Can I run Thread.critical=true , dramatically  
> > redefine operators on the core classes, redefine the operators back  
> > their original implementations, run Thread.critical=false, and expect  
> > that no other JRuby thread can get in and be broken becuase I've  
> > dramatically gutted the core classes?
> 
> You could up until about a week ago, when I proactively modified  
> critical= to just be a reentrant global lock. So basically..
> 
> Before:  
> \* critical= causes the current thread to be the only thread running \*  
> ...except on JRuby where threads run in parallel and have to reach a  
> checkpoint before they stop  
> \* ...or if code you call from within a critical section itself spins up  
> threads
> 
> After:
> 
> \* critical= acquires or releases a lock on a global mutex \* threads that  
> don't have critical sections continue running \* threads that try to  
> acquire the lock while another thread has it block
> 
> This was actually proposed by Shri Borde of IronRuby and blogged here:
> 
> [http://blogs.msdn.com/shrib/archive/2009/01/07/proposed-spec-for-ruby-s-](http://blogs.msdn.com/shrib/archive/2009/01/07/proposed-spec-for-ruby-s-)

thread-critical.aspx

> She (he?) proposes that almost all current uses of critical= intend to  
> simply delimit a critical section of code, and so a single global mutex  
> is sufficient for those cases. And in light of the fact that native  
> calls and parallel-threaded impls can't be guaranteed to deschedule  
> other threads, I think this is a much more concrete and reasonable  
> definition. So I agreed, said so on a critical-related ruby-core thread,  
> and went ahead with the change. Nothing has broken so far 🙂
> 
> For your case, I think your best bet is to either make those changes  
> before other threads start running or just accept that some of them  
> won't see your changes all at once. I believe what you want to do may  
> work on MRI, since it doesn't actually run threads in parallel and  
> critical= stops it from scheduling new ones on its own.

My goal is that other threads don't see the changes, by operating as  
follows:

In Ruby 1.8 pseudocode:

old\_critical=Thread.critical  
begin  
&nbsp;&nbsp;Thread.critical=true

&nbsp;&nbsp;[Fixnum,String].each{|klass| override\_methods\_on klass}  
&nbsp;&nbsp;result=builderblock.call  
&nbsp;&nbsp;[Fixnum,String].each{|klass| restore\_methods\_on klass}  
ensure  
&nbsp;&nbsp;Thread.critical=old\_critical  
end

Can I guarantee that other threads won't see my badly mangled Fixnum and  
String? Or is there some possiblity that another thread would continue  
executing and call (now badly broken) methods on Fixnum and String for a  
while before it hit a checkpoint that made it hit the lock? From your  
description it sounds like the latter is the case, in which case I need  
to be looking at sandboxing solutions or warn people very loudly that  
this part of the library is not thread safe and cannot be made thread  
safe. (AIUI, there's also no standard way of sandboxing right now.)

> But also note that critical= is gone in 1.9, so you should not use it  
> anyway. Use a Mutex whenever possible...it's quick, easy, and safe.
> 
> - Charlie

In Ruby 1.9 pesudocode this is only slightly different:

Thread.exclusive do  
&nbsp;&nbsp;[Fixnum,String].each{|klass| override\_methods\_on klass}  
&nbsp;&nbsp;result=builderblock.call  
&nbsp;&nbsp;[Fixnum,String].each{|klass| restore\_methods\_on klass}  
end

(The methods being overridden in this case are pretty much any useful  
binary operator on Fixnum and String, so this is pretty drastic, not to  
mention that one of those operators is != which people have been gripeing  
about a lot on ruby-core.)

--Ken

> **···**
>
> On Mon, 12 Jan 2009 10:34:26 -0500, Charles Oliver Nutter wrote:
> 
> --  
> Chanoch (Ken) Bloom. PhD candidate. Linguistic Cognition Laboratory.  
> Department of Computer Science. Illinois Institute of Technology.  
> [http://www.iit.edu/~kbloom1/](http://www.iit.edu/~kbloom1/)

---

<div class="post-metadata">

**Author:** ![Bill\_Kelly](https://avatars.discourse-cdn.com/v4/letter/b/cc9497/32.png) [@Bill\_Kelly](https://rubytalk.org/u/Bill_Kelly)\
**Post date:** [12 January 2009 23:49 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/13 "2009-01-12T23:49:03Z")

</div>

> Bill Kelly wrote:
> 
> > If we're calling untrusted code and giving it full execution privileges, then  
> > I think Binding.of\_caller is the least of our worries. The untrusted code  
> > could as easily `rm -rf ~` or innumerable other evil things.
> > 
> > Untrusted code needs to be sandboxed.
> 
> Sandboxing is made nearly impossible if calls in your own chain can escalate privileges by executing code from your binding.

Since you mention below JRuby doesn't support $SAFE, then I'm at a  
loss as to which sandboxing mechanism you refer. (Does JRuby offer an  
alternative sandboxing approach?)

It seems to me there's trusted code, and untrusted code. We allow trusted  
code to do all sorts of potentially dangerous things, including reopening and  
redefining any method in any class, etc. etc. So again, if we're talking about  
trusted code, I'm hard pressed to see the validity of holding Binding.of\_caller  
up as an exemplar of something somehow more dangerous than the myriad  
privileges already granted to trusted code in ruby.

Conversely, if we're talking about untrusted code, Binding.of\_caller seems  
a relatively unremarkable addition to an already existing great number of  
avenues by which untrusted code can affect the system unless (somehow)  
sandboxed.

If no such sandboxing mechanism exists, then why pick on Binding.of\_caller  
in particular?

> &nbsp;&nbsp;&nbsp;This is the primary reason why prototype continuation support for the JVM probably will never be shipped...the ability to implicitly access things elsewhere in the call stack has all sorts of really nasty security issues, even in a pretty secure environment like the JVM.
> 
> > Seems we could either make Binding.of\_caller not work at all if $SAFE  
> > is \>= 3 ... or preferably, if it's possible for the interpreter to determine  
> > whether the caller's binding would have a lower $SAFE level than the  
> > current binding, then only raise a SecurityException in that case.
> > 
> > Would this address your security concerns?
> 
> No, because JRuby doesn't support $SAFE. It's a blunt instrument that I don't think anyone has ever audited for actual safety. So as a result, anyone believing $SAFE is actually safe is probably introducing even more risk into their apps.
> 
> Also, $SAFE is a global thing, and you can't localize it to a given binding, so that wouldn't work anyway.

It's thread local. And it apparently somehow does get localized to a  
given binding (?) because ruby remembers the $SAFE level at which a  
lexical closure was compiled (or at least, a proc.)

For example, if a thread is at $SAFE=4, and calls a proc which was  
compiled at $SAFE=0, then the proc executes at $SAFE=0.

I do share your concerns about $SAFE never having been formally  
audited for security, and I'd agree it would be foolish to assume there  
don't exist some undiscovered holes in the system.

(On the other hand, in practical terms, we live with as yet undiscovered  
security holes in windows, linux, IIS, apache, etc. every day too.)

That said, it appears $SAFE=4 was designed with the \_intent\_ to  
provide a secure sandbox. And it seems to me the $SAFE mechanism  
could as easily disallow inappropriate uses of Binding.of\_caller, just  
as it currently disallows the reopening of classes and modules, etc.

> Honestly, if you want a binding, pass one in.

Been there, done that.

As Matz pointed out with respect to other dangerous features:

&nbsp;&nbsp;&nbsp;&nbsp;"open class" is so strong (often too strong), we can break things easily.  
&nbsp;&nbsp;&nbsp;&nbsp;In other word, Ruby trust you to give you sharp knives, where Python don’t.  
&nbsp;&nbsp;&nbsp;&nbsp;From the Python point of view, it’s wrong, I guess.

Again, I don't see why Binding.of\_caller is particularly sharper than many  
other knives in ruby. (If I try to imagine writing malicious code I know will  
be executed with full privileges, Binding.of\_caller isn't the first tool that  
comes to mind when I contemplate all the nefarious possibilities.)

Regards,

Bill

> **···**
>
> From: "Charles Oliver Nutter" \<charles.nutter@sun.com\>

---

<div class="post-metadata">

**Author:** ![Ken\_Bloom](https://avatars.discourse-cdn.com/v4/letter/k/f08c70/32.png) [@Ken\_Bloom](https://rubytalk.org/u/Ken_Bloom)\
**Post date:** [12 January 2009 18:09 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/14 "2009-01-12T18:09:20Z")

</div>

> > Ken Bloom wrote:
> > 
> > > Which reminds me of another question I had. You were discussing  
> > > somewhere else how Thread.critical works in JRuby. Does  
> > > Thread.critical / Thread.exclusive in JRuby protect other threads  
> > > against changes to the core class methods? Can I run  
> > > Thread.critical=true , dramatically redefine operators on the core  
> > > classes, redefine the operators back their original implementations,  
> > > run Thread.critical=false, and expect that no other JRuby thread can  
> > > get in and be broken becuase I've dramatically gutted the core  
> > > classes?
> > 
> > You could up until about a week ago, when I proactively modified  
> > critical= to just be a reentrant global lock. So basically..
> > 
> > Before:  
> > \* critical= causes the current thread to be the only thread running \*  
> > ...except on JRuby where threads run in parallel and have to reach a  
> > checkpoint before they stop  
> > \* ...or if code you call from within a critical section itself spins up  
> > threads
> > 
> > After:
> > 
> > \* critical= acquires or releases a lock on a global mutex \* threads  
> > that don't have critical sections continue running \* threads that try  
> > to acquire the lock while another thread has it block
> > 
> > This was actually proposed by Shri Borde of IronRuby and blogged here:
> > 
> > [http://blogs.msdn.com/shrib/archive/2009/01/07/proposed-spec-for-ruby-](http://blogs.msdn.com/shrib/archive/2009/01/07/proposed-spec-for-ruby-)

s-

> thread-critical.aspx
> 
> > She (he?) proposes that almost all current uses of critical= intend to  
> > simply delimit a critical section of code, and so a single global mutex  
> > is sufficient for those cases. And in light of the fact that native  
> > calls and parallel-threaded impls can't be guaranteed to deschedule  
> > other threads, I think this is a much more concrete and reasonable  
> > definition. So I agreed, said so on a critical-related ruby-core  
> > thread, and went ahead with the change. Nothing has broken so far 🙂
> > 
> > For your case, I think your best bet is to either make those changes  
> > before other threads start running or just accept that some of them  
> > won't see your changes all at once. I believe what you want to do may  
> > work on MRI, since it doesn't actually run threads in parallel and  
> > critical= stops it from scheduling new ones on its own.
> 
> My goal is that other threads don't see the changes, by operating as  
> follows:
> 
> In Ruby 1.8 pseudocode:
> 
> old\_critical=Thread.critical  
> begin  
> &nbsp;&nbsp;Thread.critical=true
> 
> &nbsp;&nbsp;[Fixnum,String].each{|klass| override\_methods\_on klass}  
> &nbsp;&nbsp;result=builderblock.call  
> &nbsp;&nbsp;[Fixnum,String].each{|klass| restore\_methods\_on klass}  
> ensure  
> &nbsp;&nbsp;Thread.critical=old\_critical  
> end
> 
> Can I guarantee that other threads won't see my badly mangled Fixnum and  
> String? Or is there some possiblity that another thread would continue  
> executing and call (now badly broken) methods on Fixnum and String for a  
> while before it hit a checkpoint that made it hit the lock? From your  
> description it sounds like the latter is the case, in which case I need  
> to be looking at sandboxing solutions or warn people very loudly that  
> this part of the library is not thread safe and cannot be made thread  
> safe. (AIUI, there's also no standard way of sandboxing right now.)
> 
> > But also note that critical= is gone in 1.9, so you should not use it  
> > anyway. Use a Mutex whenever possible...it's quick, easy, and safe.
> > 
> > - Charlie
> 
> In Ruby 1.9 pesudocode this is only slightly different:
> 
> Thread.exclusive do  
> &nbsp;&nbsp;[Fixnum,String].each{|klass| override\_methods\_on klass}  
> &nbsp;&nbsp;result=builderblock.call  
> &nbsp;&nbsp;[Fixnum,String].each{|klass| restore\_methods\_on klass}  
> end
> 
> (The methods being overridden in this case are pretty much any useful  
> binary operator on Fixnum and String, so this is pretty drastic, not to  
> mention that one of those operators is != which people have been  
> gripeing about a lot on ruby-core.)
> 
> --Ken

Oh, shoot. I just realized I'd have the same problem if code passed to  
the s-expression builder called user-defined custom methods (which is  
actually a desired behavior) to use their results. Those methods would be  
broken inside by the wretching monkey patching going on. I guess it's  
probably best to abandon the idea of the s-expression builder completely,  
or do it with a string, an explicit binding, and ripper.

--Ken

> **···**
>
> On Mon, 12 Jan 2009 10:59:52 -0600, Ken Bloom wrote:
> 
> > On Mon, 12 Jan 2009 10:34:26 -0500, Charles Oliver Nutter wrote:
> 
> --  
> Chanoch (Ken) Bloom. PhD candidate. Linguistic Cognition Laboratory.  
> Department of Computer Science. Illinois Institute of Technology.  
> [http://www.iit.edu/~kbloom1/](http://www.iit.edu/~kbloom1/)

---

<div class="post-metadata">

**Author:** ![Charles\_Oliver\_Nutte](https://avatars.discourse-cdn.com/v4/letter/c/71e660/32.png) [@Charles\_Oliver\_Nutte](https://rubytalk.org/u/Charles_Oliver_Nutte)\
**Post date:** [12 January 2009 21:31 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/15 "2009-01-12T21:31:15Z")

</div>

Ken Bloom wrote:

> My goal is that other threads don't see the changes, by operating as follows:
> 
> In Ruby 1.8 pseudocode:
> 
> old\_critical=Thread.critical  
> begin  
> &nbsp;&nbsp;Thread.critical=true  
> &nbsp;&nbsp;&nbsp;[Fixnum,String].each{|klass| override\_methods\_on klass}  
> &nbsp;&nbsp;result=builderblock.call  
> &nbsp;&nbsp;[Fixnum,String].each{|klass| restore\_methods\_on klass}  
> ensure Thread.critical=old\_critical  
> end
> 
> Can I guarantee that other threads won't see my badly mangled Fixnum and String? Or is there some possiblity that another thread would continue executing and call (now badly broken) methods on Fixnum and String for a while before it hit a checkpoint that made it hit the lock? From your description it sounds like the latter is the case, in which case I need to be looking at sandboxing solutions or warn people very loudly that this part of the library is not thread safe and cannot be made thread safe. (AIUI, there's also no standard way of sandboxing right now.)

The latter...you can't guarantee the other threads will necessarily stop before they see your breaking changes. You need to look at sandboxing, or help Matz implement selector namespaces (which I'd love to help with too).

> In Ruby 1.9 pesudocode this is only slightly different:
> 
> Thread.exclusive do  
> &nbsp;&nbsp;[Fixnum,String].each{|klass| override\_methods\_on klass}  
> &nbsp;&nbsp;result=builderblock.call  
> &nbsp;&nbsp;[Fixnum,String].each{|klass| restore\_methods\_on klass}  
> end

This only guarantees only one thread can execute that block of code; it doesn't stop other threads from running:

◆ ruby1.9 -e "require 'thread'; Thread.new { sleep 1; puts 'hello'; redo }; Thread.exclusive do; sleep; end"  
hello  
^C

- Charlie

---

<div class="post-metadata">

**Author:** ![Charles\_Oliver\_Nutte](https://avatars.discourse-cdn.com/v4/letter/c/71e660/32.png) [@Charles\_Oliver\_Nutte](https://rubytalk.org/u/Charles_Oliver_Nutte)\
**Post date:** [13 January 2009 17:48 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/16 "2009-01-13T17:48:38Z")

</div>

Bill Kelly wrote:

> > Sandboxing is made nearly impossible if calls in your own chain can escalate privileges by executing code from your binding.
> 
> Since you mention below JRuby doesn't support $SAFE, then I'm at a  
> loss as to which sandboxing mechanism you refer. (Does JRuby offer an  
> alternative sandboxing approach?)

The JVM has its own built-in security mechanisms, and we do nothing to override or subvert them. We've considered adding portions of $SAFE like limiting eval and loading of code from the filesystem, but largely $SAFE is so amorphous and untested we've opted to leave it basically unimplemented. Also, a substantial portion of $SAFE's guarantees come from tainting, which requires checking taint on objects over and over and over again. I don't think it's a realistic or reliable security mechanism as it exists today.

> It seems to me there's trusted code, and untrusted code. We allow trusted  
> code to do all sorts of potentially dangerous things, including reopening and  
> redefining any method in any class, etc. etc. So again, if we're talking about  
> trusted code, I'm hard pressed to see the validity of holding Binding.of\_caller  
> up as an exemplar of something somehow more dangerous than the myriad  
> privileges already granted to trusted code in ruby.

Without Binding.of\_caller, no trusted or untrusted Ruby code can access a method's local variables unless that method passes a block or binding explicitly. of\_caller opens up every method to that possibility. You don't think that exposure is problematic?

> Conversely, if we're talking about untrusted code, Binding.of\_caller seems  
> a relatively unremarkable addition to an already existing great number of  
> avenues by which untrusted code can affect the system unless (somehow)  
> sandboxed.

It goes well above and beyond existing mechanisms since it exposes details of a caller's bindings that would never be accessible through any other means.

Similar logic kicked retry out of 1.9, since it caused the original receiver and arguments to be reevaluated, whether the caller that behavior or not.

In general we should avoid adding the potential for locally-scoped side effects that no amount of inspection can detect. It opens up a big can of worms if you can't look at a method and know each step along the way that the variables are going to be what you set them do, and that no call you make will invalidate that expectation.

There's also logistical concerns. If you had Binding.of\_caller available, how do you ensure you're not irreparably damaging the caller's context?

def do\_call  
&nbsp;&nbsp;&nbsp;binding = Binding.of\_caller  
&nbsp;&nbsp;&nbsp;eval "some\_local\_var = nil", binding  
end

def innocent  
&nbsp;&nbsp;&nbsp;some\_local\_var = important\_value  
&nbsp;&nbsp;&nbsp;do\_call  
&nbsp;&nbsp;&nbsp;# now, without me assigning it, some\_local\_var has been changed  
end

This is a horrible breach of trust that should never, ever be made possible in Ruby.

> It's thread local. And it apparently somehow does get localized to a  
> given binding (?) because ruby remembers the $SAFE level at which a  
> lexical closure was compiled (or at least, a proc.)
> 
> For example, if a thread is at $SAFE=4, and calls a proc which was  
> compiled at $SAFE=0, then the proc executes at $SAFE=0.
> 
> I do share your concerns about $SAFE never having been formally  
> audited for security, and I'd agree it would be foolish to assume there  
> don't exist some undiscovered holes in the system.
> 
> (On the other hand, in practical terms, we live with as yet undiscovered  
> security holes in windows, linux, IIS, apache, etc. every day too.)

$SAFE is one place where we simply can't get by with the loose specifications in place for the rest of Ruby. I'd welcome discussions on how to make $SAFE or something similar a formally-specified security mechanism for Ruby. But as it stands now, I think it's too vague and requires too many little bits of code sprinkled all over the codebase to function correctly. I'm no security expert, but relying on a million tiny little taint checks to ensure the sandbox remains secure seems totally infeasible. If you have just \*one\* core method that doesn't propagate tainting correctly, you're screwed.

> That said, it appears $SAFE=4 was designed with the \_intent\_ to  
> provide a secure sandbox. And it seems to me the $SAFE mechanism  
> could as easily disallow inappropriate uses of Binding.of\_caller, just  
> as it currently disallows the reopening of classes and modules, etc.

You're right about $SAFE locality...a binding does appear to keep a reference to its original thread's state, so it sees that thread's $SAFE. But of course that's not really applicable here, since $SAFE propagates down normal call stacks, and Binding.of\_caller is intended for normal call stacks. So caller and callee would always have the same $SAFE level either way.

If you're talking about doing Binding.of\_caller from within a proc body that came from another thread that has a different $SAFE level, with the caller calling Proc#call and the callee using that call to get the caller's binding with Binding.of\_caller...I think we've probably got other complexity and threading issues to consider before we try to secure Binding.of\_caller.

Here's an example of what you'd have to do to have a different caller $SAFE than callee:

puts "safe outside: #{$SAFE}"  
x = nil  
Thread.new { x = proc { puts "safe in proc: #{$SAFE}" } }.join  
$SAFE = 1  
puts "safe escalated: #{$SAFE}"  
x.call  
new\_safe = eval "$SAFE", x  
puts "safe from binding #{new\_safe}"

This outputs 0, 1, 0, 1 as you'd expect. So the only way you'd potentially have a different safe level for a caller than for a callee is if you were evaluating code against a binding with a different save level (at which point we're explicitly using a binding anyway) or calling a proc (where it would be pretty rare to see Binding.of\_caller). So I think $SAFE is not a particularly useful way to secure individual frames in the call stack.

> Again, I don't see why Binding.of\_caller is particularly sharper than many  
> other knives in ruby. (If I try to imagine writing malicious code I know will  
> be executed with full privileges, Binding.of\_caller isn't the first tool that  
> comes to mind when I contemplate all the nefarious possibilities.)

It's WAY sharper because it invalidates infallible truths about execution flow in a method body. Today, you can be guaranteed that unless you explicitly pass a binding to another call (either through eval/binding or by passing a block) none of your local variables will be mutated unless you mutate them yourself. Binding.of\_caller breaks that assumption for all code everywhere. I don't want to live in that world.

- Charlie

---

<div class="post-metadata">

**Author:** ![Ken\_Bloom](https://avatars.discourse-cdn.com/v4/letter/k/f08c70/32.png) [@Ken\_Bloom](https://rubytalk.org/u/Ken_Bloom)\
**Post date:** [13 January 2009 05:10 UTC](https://rubytalk.org/t/binding-of-caller-examples-dont-work/51088/17 "2009-01-13T05:10:17Z")

</div>

Okay. In that case, I'd better read Pickaxe for 1.9 from cover to cover  
before I try to use 1.9.

(Ducks and runs)  
--Ken

> **···**
>
> On Mon, 12 Jan 2009 16:31:15 -0500, Charles Oliver Nutter wrote:
> 
> > > In Ruby 1.9 pesudocode this is only slightly different:
> > > 
> > > Thread.exclusive do  
> > > &nbsp;&nbsp;[Fixnum,String].each{|klass| override\_methods\_on klass}  
> > > &nbsp;&nbsp;result=builderblock.call  
> > > &nbsp;&nbsp;[Fixnum,String].each{|klass| restore\_methods\_on klass}  
> > > end
> > 
> > This only guarantees only one thread can execute that block of code; it  
> > doesn't stop other threads from running:
> > 
> > ◆ ruby1.9 -e "require 'thread'; Thread.new { sleep 1; puts 'hello'; redo  
> > }; Thread.exclusive do; sleep; end"  
> > hello  
> > hello  
> > hello  
> > hello  
> > hello  
> > ^C
> > 
> > - Charlie
> 
> --  
> Chanoch (Ken) Bloom. PhD candidate. Linguistic Cognition Laboratory.  
> Department of Computer Science. Illinois Institute of Technology.  
> [http://www.iit.edu/~kbloom1/](http://www.iit.edu/~kbloom1/)
