Issue #7046 has been updated by headius (Charles Nutter).


In JRuby it does not appear that dup'ing a binding copies all structures over, so we'd need to fix that as well to use TOPLEVEL_BINDING.dup.

It appears we match 1.8.7 behavior still, for Binding#dup:


system ~/projects/jruby $ ruby-1.8.7-p358 -e "eval 'a = 1', TOPLEVEL_BINDING.dup; eval 'puts a', TOPLEVEL_BINDING.dup"
1

system ~/projects/jruby $ jruby -e "eval 'a = 1', TOPLEVEL_BINDING.dup; eval 'puts a', TOPLEVEL_BINDING.dup"
1

system ~/projects/jruby $ ruby-1.9.3 -e "eval 'a = 1', TOPLEVEL_BINDING.dup; eval 'puts a', TOPLEVEL_BINDING.dup"
<main>:in `<main>': undefined local variable or method `a' for main:Object (NameError)
	from -e:1:in `eval'
	from -e:1:in `<main>'

Given that we would not be releasing patched ERB in any release other than one with this fixed, I think TOPLEVEL_BINDING.dup is probably the simplest way.
----------------------------------------
Bug #7046: ERB#run and ERB#result are not safe for concurrent use
https://bugs.ruby-lang.org/issues/7046#change-29716

Author: headius (Charles Nutter)
Status: Open
Priority: Normal
Assignee: 
Category: lib
Target version: 
ruby -v: 2.0.0.dev


ERB#run and ERB#result both accept an optional binding under which to execute the template. However, if none is given, they both use TOPLEVEL_BINDING by default. Given that by default, the _erbout variable is used for the String into which ERB output gets appended, this causes concurrent template execution on the same thread or separate threads to modify the same buffer. On JRuby, this led to overflow errors when in-progress writes saw their buffers suddenly altered.

This also causes any variables or values evaluated at TOPLEVEL to remain referenced.

I have provided a patch (https://gist.github.com/3764377) that is still very close to the toplevel binding, but instead uses the following logic each call to get a new, isolated binding in which to run the template:

eval "proc{binding}.call", TOPLEVEL_BINDING

This provides visibility to all values at TOPLEVEL, isolates runs to reduce concurrency issues, and guarantees any values stored in the binding will be thrown away after execution.

This fix should be backported to 1.9.3 at minimum.


-- 
http://bugs.ruby-lang.org/