diff --git a/lib/erb.rb b/lib/erb.rb index fbd146e..a4b481a 100644 --- a/lib/erb.rb +++ b/lib/erb.rb @@ -778,6 +778,9 @@ # [template processor]: https://en.wikipedia.org/wiki/Template_processor # class ERB + IDENTITY_METHOD = BasicObject.instance_method(:equal?) # :nodoc: + private_constant :IDENTITY_METHOD + # :markup: markdown # # :call-seq: @@ -1007,7 +1010,7 @@ def run(b=new_toplevel) # [local binding]: rdoc-ref:ERB@Local+Binding # def result(b=new_toplevel) - unless @_init.equal?(self.class.singleton_class) + unless initialized_by_new? raise ArgumentError, "not initialized" end eval(@src, b, (@filename || '(erb)'), @lineno) @@ -1061,6 +1064,11 @@ def new_toplevel(vars = nil) end private :new_toplevel + def initialized_by_new? # :nodoc: + IDENTITY_METHOD.bind_call(@_init, self.class.singleton_class) + end + private :initialized_by_new? + # :markup: markdown # # :call-seq: @@ -1087,7 +1095,7 @@ def new_toplevel(vars = nil) # ``` # def def_method(mod, methodname, fname='(ERB)') - unless @_init.equal?(self.class.singleton_class) + unless initialized_by_new? raise ArgumentError, "not initialized" end src = self.src.sub(/^(?!#|$)/) {"def #{methodname}\n"} << "\nend\n" diff --git a/test/erb/test_erb.rb b/test/erb/test_erb.rb index b2eaa4e..1de8925 100644 --- a/test/erb/test_erb.rb +++ b/test/erb/test_erb.rb @@ -85,10 +85,24 @@ def test_concurrent_default_binding end class TestERBCore < Test::Unit::TestCase + class AlwaysEqual + def equal?(_other) + true + end + end + def setup @erb = ERB end + def marshal_loaded_erb(init, src: "") + erb = ERB.allocate + erb.instance_variable_set(:@src, src) + erb.instance_variable_set(:@lineno, 1) + erb.instance_variable_set(:@_init, init) + Marshal.load(Marshal.dump(erb)) + end + def test_version assert_equal(String, @erb.version.class) end @@ -664,6 +678,11 @@ def test_prohibited_marshal_load assert_raise(ArgumentError) {erb.result} end + def test_prohibited_marshal_load_result_with_overridden_equal + erb = marshal_loaded_erb(AlwaysEqual.new, src: "raise 'unreachable'") + assert_raise(ArgumentError) {erb.result} + end + def test_prohibited_marshal_load_def_method erb = ERB.allocate erb.instance_variable_set(:@src, "") @@ -673,6 +692,11 @@ def test_prohibited_marshal_load_def_method assert_raise(ArgumentError) {erb.def_method(Class.new, 'render')} end + def test_prohibited_marshal_load_def_method_with_overridden_equal + erb = marshal_loaded_erb(AlwaysEqual.new) + assert_raise(ArgumentError) {erb.def_method(Class.new, 'render')} + end + def test_prohibited_marshal_load_def_module erb = ERB.allocate erb.instance_variable_set(:@src, "")