Check method existence for Enumerators; fix #3920

The issue #3920 was fixed but the fundamental flaw of lack of stack
depth check along with fibers still remains, even though it's not
easy to cause the issue.  Use `MRB_GC_FIXED_ARENA` to avoid the issue
for workaround.

After this patch, `obj.to_enum` raises `ArgumentError` if the object
does not respond to the enumerating method. This is incompatible to
CRuby but I think this behavior is better and CRuby should be updated
to behave like this.
parent 31a961ac
...@@ -44,7 +44,7 @@ class Enumerator ...@@ -44,7 +44,7 @@ class Enumerator
def to_enum(meth=:each, *args, &block) def to_enum(meth=:each, *args, &block)
unless self.respond_to?(meth) unless self.respond_to?(meth)
raise NoMethodError, "undefined method #{meth}" raise ArgumentError, "undefined method #{meth}"
end end
lz = Lazy.new(self, &block) lz = Lazy.new(self, &block)
lz.obj = self lz.obj = self
......
...@@ -614,6 +614,9 @@ module Kernel ...@@ -614,6 +614,9 @@ module Kernel
# enum.first(4) # => [1, 1, 1, 2] # enum.first(4) # => [1, 1, 1, 2]
# #
def to_enum(meth=:each, *args) def to_enum(meth=:each, *args)
unless self.respond_to?(meth)
raise ArgumentError, "undefined method #{meth}"
end
Enumerator.new self, meth, *args Enumerator.new self, meth, *args
end end
alias enum_for to_enum alias enum_for to_enum
......
...@@ -22,8 +22,7 @@ assert 'Enumerator.new' do ...@@ -22,8 +22,7 @@ assert 'Enumerator.new' do
assert_equal [1,2,3], Enumerator.new(@obj, :foo, 1,2,3).to_a assert_equal [1,2,3], Enumerator.new(@obj, :foo, 1,2,3).to_a
assert_equal [1,2,3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3) assert_equal [1,2,3], Enumerator.new { |y| i = 0; loop { y << (i += 1) } }.take(3)
assert_raise(ArgumentError) { Enumerator.new } assert_raise(ArgumentError) { Enumerator.new }
enum = @obj.to_enum assert_raise(ArgumentError) { @obj.to_enum }
assert_raise(NoMethodError) { enum.each {} }
# examples # examples
fib = Enumerator.new do |y| fib = Enumerator.new do |y|
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment