Skip to content

Commit

Permalink
Merge pull request #3987 from eregon/fix_warn_stack_overflow2
Browse files Browse the repository at this point in the history
Preserve `self` when calling the original Kernel#warn method
  • Loading branch information
deivid-rodriguez committed Oct 21, 2020
2 parents 61447f3 + 4b0f57f commit fac8d59
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 6 deletions.
11 changes: 5 additions & 6 deletions lib/rubygems/core_ext/kernel_warn.rb
Expand Up @@ -6,7 +6,7 @@
module Kernel
rubygems_path = "#{__dir__}/" # Frames to be skipped start with this path.

original_warn = method(:warn)
original_warn = instance_method(:warn)

remove_method :warn

Expand All @@ -17,9 +17,9 @@ class << self
module_function define_method(:warn) {|*messages, **kw|
unless uplevel = kw[:uplevel]
if Gem.java_platform?
return original_warn.call(*messages)
return original_warn.bind(self).call(*messages)
else
return original_warn.call(*messages, **kw)
return original_warn.bind(self).call(*messages, **kw)
end
end

Expand All @@ -45,11 +45,10 @@ class << self
end
end
end
uplevel = start
kw[:uplevel] = start
end

kw[:uplevel] = uplevel
original_warn.call(*messages, **kw)
original_warn.bind(self).call(*messages, **kw)
}
end
end
41 changes: 41 additions & 0 deletions test/rubygems/test_require.rb
Expand Up @@ -677,6 +677,47 @@ def test_require_bundler_with_bundler_version
end
end
end

def test_no_crash_when_overriding_warn_with_warning_module
skip "https://github.com/oracle/truffleruby/issues/2109" if RUBY_ENGINE == "truffleruby"

Dir.mktmpdir("warn_test") do |dir|
File.write(dir + "/main.rb", "module Warning; def warn(str); super; end; end; warn 'Foo Bar'")
_, err = capture_subprocess_io do
system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "main.rb")
end
assert_match(/Foo Bar\n$/, err)
_, err = capture_subprocess_io do
system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "main.rb")
end
assert_match(/Foo Bar\n$/, err)
end
end

def test_expected_backtrace_location_when_inheriting_from_basic_object_and_including_kernel
Dir.mktmpdir("warn_test") do |dir|
File.write(dir + "/main.rb", "\nrequire 'sub'\n")
File.write(dir + "/sub.rb", <<-'RUBY')
require 'rubygems'
class C < BasicObject
include ::Kernel
def deprecated
warn "This is a deprecated method", uplevel: 2
end
end
C.new.deprecated
RUBY

_, err = capture_subprocess_io do
system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb")
end
assert_match(/main\.rb:2: warning: This is a deprecated method$/, err)
_, err = capture_subprocess_io do
system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb")
end
assert_match(/main\.rb:2: warning: This is a deprecated method$/, err)
end
end
end

private
Expand Down

0 comments on commit fac8d59

Please sign in to comment.