Project

General

Profile

Actions

Bug #16942

closed

instance_method causes an infinite loop with prepend, include and private

Added by pocke (Masataka Kuwabara) over 4 years ago. Updated over 4 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 2.8.0dev (2020-06-09T13:51:54Z master 7f3efee102) [x86_64-linux]
[ruby-core:98691]

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

Actions #3

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]

Actions #4

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
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0