Bug #16942
closedinstance_method causes an infinite loop with prepend, include and private
Description
instance_method
causes an infinite loop with the following code.
module M
def x
end
end
module M2
include M
private :x
end
::Object.prepend(M2)
# infinite loop
p Object.instance_method(:x)
I've confirmed it on the master branch. The commit is 7f3efee102.
But instance_method
works correctly with Ruby 2.7.1.
Updated by jeremyevans0 (Jeremy Evans) over 4 years ago
You get the same infinite loop in 2.7.1 if M2
prepends a module (or otherwise has an origin class created for it):
module M
def x
end
end
module M2
include M
private :x
prepend Module.new
end
::Object.prepend(M2)
# infinite loop
p Object.instance_method(:x)
It's just in master all modules that are included or prepended into other modules or classes automatically have an origin class, so the bug in instance_method
is now exposed in additional cases.
Updated by jeremyevans0 (Jeremy Evans) over 4 years ago
This issue first occurred in Ruby 2.3.
The problematic code is the goto again
loop in mnew_internal
. You can end up with a situation where klass
is the same or an ancestor of RCLASS_SUPER(me->owner)
, so klass
never changes. This is possible to work around by detecting this case and using RCLASS_SUPER(klass)
instead of RCLASS_SUPER(me->owner)
in this case. However, this approach is O(m*n), where m is the number of ZSUPER methods and n is the length of the super chain of RCLASS_SUPER(me->owner)
. Unfortunately, I don't have enough knowledge of the internals to determine if there is a more efficient solution, or if the work around will cause other problems.
I submitted a pull request for the work around: https://github.com/ruby/ruby/pull/3201
Updated by jeremyevans (Jeremy Evans) over 4 years ago
- Status changed from Open to Closed
Applied in changeset git|ad0eccf840f692694e63ec72c8496dc106e603ed.
Work around infinite loop when overriding method visibility in prepended module (#3201)
For ZSUPER methods with no defined class for the method entry, start the next lookup at the superclass of the origin class of the method owner, instead of the superclass of the method owner.
Fixes [Bug #16942]
Updated by nagachika (Tomoyuki Chikanaga) over 4 years ago
- Backport changed from 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN to 2.5: REQUIRED, 2.6: REQUIRED, 2.7: REQUIRED