Skip to content

Commit 9d017be

Browse files
k0kubunTristanInSec
andcommitted
Prohibit def_method on marshal-loaded ERB instances
Extends the @_init guard to def_method so that an ERB object created via Marshal.load (which bypasses initialize) raises ArgumentError instead of evaluating arbitrary source. def_module and def_class both delegate to def_method and are covered by the same check. Co-authored-by: Tristan Madani <TristanInSec@gmail.com>
1 parent 9c8fa8a commit 9d017be

2 files changed

Lines changed: 30 additions & 0 deletions

File tree

lib/erb.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,6 +1087,9 @@ def new_toplevel(vars = nil)
10871087
# ```
10881088
#
10891089
def def_method(mod, methodname, fname='(ERB)')
1090+
unless @_init.equal?(self.class.singleton_class)
1091+
raise ArgumentError, "not initialized"
1092+
end
10901093
src = self.src.sub(/^(?!#|$)/) {"def #{methodname}\n"} << "\nend\n"
10911094
mod.module_eval do
10921095
eval(src, binding, fname, -1)

test/erb/test_erb.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,33 @@ def test_prohibited_marshal_load
664664
assert_raise(ArgumentError) {erb.result}
665665
end
666666

667+
def test_prohibited_marshal_load_def_method
668+
erb = ERB.allocate
669+
erb.instance_variable_set(:@src, "")
670+
erb.instance_variable_set(:@lineno, 1)
671+
erb.instance_variable_set(:@_init, true)
672+
erb = Marshal.load(Marshal.dump(erb))
673+
assert_raise(ArgumentError) {erb.def_method(Class.new, 'render')}
674+
end
675+
676+
def test_prohibited_marshal_load_def_module
677+
erb = ERB.allocate
678+
erb.instance_variable_set(:@src, "")
679+
erb.instance_variable_set(:@lineno, 1)
680+
erb.instance_variable_set(:@_init, true)
681+
erb = Marshal.load(Marshal.dump(erb))
682+
assert_raise(ArgumentError) {erb.def_module}
683+
end
684+
685+
def test_prohibited_marshal_load_def_class
686+
erb = ERB.allocate
687+
erb.instance_variable_set(:@src, "")
688+
erb.instance_variable_set(:@lineno, 1)
689+
erb.instance_variable_set(:@_init, true)
690+
erb = Marshal.load(Marshal.dump(erb))
691+
assert_raise(ArgumentError) {erb.def_class}
692+
end
693+
667694
def test_multi_line_comment_lineno
668695
erb = ERB.new(<<~EOS)
669696
<%= __LINE__ %>

0 commit comments

Comments
 (0)