diff --git a/lib/irb/source_finder.rb b/lib/irb/source_finder.rb index 4e9cdc462a..ad9ee21026 100644 --- a/lib/irb/source_finder.rb +++ b/lib/irb/source_finder.rb @@ -34,7 +34,8 @@ module IRB return unless receiver.respond_to?(method, true) file, line = method_target(receiver, super_level, method, "receiver") end - if file && line && File.exist?(file) + # If the line is zero, it means that the target's source is probably in a binary file, which we should ignore. + if file && line && !line.zero? && File.exist?(file) Source.new(file: file, first_line: line, last_line: find_end(file, line)) end end diff --git a/test/irb/cmd/test_show_source.rb b/test/irb/cmd/test_show_source.rb index 12abae3c72..c2608926e8 100644 --- a/test/irb/cmd/test_show_source.rb +++ b/test/irb/cmd/test_show_source.rb @@ -300,5 +300,24 @@ module TestIRB assert_match(%r[#{@ruby_file.to_path}:5\s+class Bar\r\n end], out) end + + def test_show_source_ignores_binary_source_file + write_ruby <<~RUBY + # io-console is an indirect dependency of irb + require "io/console" + + binding.irb + RUBY + + out = run_ruby_file do + # IO::ConsoleMode is defined in io-console gem's C extension + type "show_source IO::ConsoleMode" + type "exit" + end + + # A safeguard to make sure the test subject is actually defined + refute_match(/NameError/, out) + assert_match(%r[Error: Couldn't locate a definition for IO::ConsoleMode], out) + end end end