ruby/test/rubygems/test_gem_gem_runner.rb
David Rodríguez e7518a7859 Validate user input encoding
If the user has the encoding of her system messed up, she may end up
sending us incorrectly encoding input, causing "invalid byte sequence in
UTF-8" errors at random places.

These errors can be forced on a system without encoding issues with
something like:

```
$ gem install$(echo -e "\xFF") foo
/Users/deivid/.asdf/installs/ruby/3.2.1/lib/ruby/site_ruby/3.2.0/rubygems/config_file.rb:534:in `block in set_config_file_name': invalid byte sequence in UTF-8 (ArgumentError)
	from /Users/deivid/.asdf/installs/ruby/3.2.1/lib/ruby/site_ruby/3.2.0/rubygems/config_file.rb:530:in `each'
	from /Users/deivid/.asdf/installs/ruby/3.2.1/lib/ruby/site_ruby/3.2.0/rubygems/config_file.rb:530:in `set_config_file_name'
	from /Users/deivid/.asdf/installs/ruby/3.2.1/lib/ruby/site_ruby/3.2.0/rubygems/config_file.rb:177:in `initialize'
	from /Users/deivid/.asdf/installs/ruby/3.2.1/lib/ruby/site_ruby/3.2.0/rubygems/gem_runner.rb:71:in `new'
	from /Users/deivid/.asdf/installs/ruby/3.2.1/lib/ruby/site_ruby/3.2.0/rubygems/gem_runner.rb:71:in `do_configuration'
	from /Users/deivid/.asdf/installs/ruby/3.2.1/lib/ruby/site_ruby/3.2.0/rubygems/gem_runner.rb:33:in `run'
	from /Users/deivid/.asdf/installs/ruby/3.2.1/bin/gem:10:in `<main>'
```

This commit makes RubyGems print a better error in this case:

```
$ ruby -Ilib bin/gem install$(echo -e "\xFF") foo
/Users/deivid/Code/rubygems/rubygems/lib/rubygems/gem_runner.rb:75:in `validate_encoding': invalid argument: 'install�' has invalid encoding (Gem::OptionParser::InvalidArgument)
	from /Users/deivid/Code/rubygems/rubygems/lib/rubygems/gem_runner.rb:31:in `run'
	from bin/gem:10:in `<main>'
```
2024-11-04 10:18:55 +00:00

125 lines
2.8 KiB
Ruby

# frozen_string_literal: true
require_relative "helper"
class TestGemGemRunner < Gem::TestCase
def setup
require "rubygems/command"
@orig_args = Gem::Command.build_args
@orig_specific_extra_args = Gem::Command.specific_extra_args_hash.dup
@orig_extra_args = Gem::Command.extra_args.dup
super
@orig_gem_home = ENV["GEM_HOME"]
ENV["GEM_HOME"] = @gemhome
require "rubygems/gem_runner"
@runner = Gem::GemRunner.new
end
def teardown
ENV["GEM_HOME"] = @orig_gem_home
super
Gem::Command.build_args = @orig_args
Gem::Command.specific_extra_args_hash = @orig_specific_extra_args
Gem::Command.extra_args = @orig_extra_args
end
def test_do_configuration
Gem.clear_paths
temp_conf = File.join @tempdir, ".gemrc"
other_gem_path = File.join @tempdir, "other_gem_path"
other_gem_home = File.join @tempdir, "other_gem_home"
Gem.ensure_gem_subdirectories other_gem_path
Gem.ensure_gem_subdirectories other_gem_home
File.open temp_conf, "w" do |fp|
fp.puts "gem: --commands"
fp.puts "gemhome: #{other_gem_home}"
fp.puts "gempath:"
fp.puts " - #{other_gem_path}"
fp.puts "rdoc: --all"
end
gr = Gem::GemRunner.new
gr.send :do_configuration, %W[--config-file #{temp_conf}]
assert_equal [other_gem_path, other_gem_home], Gem.path
assert_equal %w[--commands], Gem::Command.extra_args
end
def test_validate_encoding
assert_raise Gem::OptionParser::InvalidArgument do
@runner.run(["install\xFF", "foo"])
end
end
def test_extract_build_args
args = %w[]
assert_equal [], @runner.extract_build_args(args)
assert_equal %w[], args
args = %w[foo]
assert_equal [], @runner.extract_build_args(args)
assert_equal %w[foo], args
args = %w[--foo]
assert_equal [], @runner.extract_build_args(args)
assert_equal %w[--foo], args
args = %w[--foo --]
assert_equal [], @runner.extract_build_args(args)
assert_equal %w[--foo], args
args = %w[--foo -- --bar]
assert_equal %w[--bar], @runner.extract_build_args(args)
assert_equal %w[--foo], args
end
def test_query_is_deprecated
args = %w[query]
use_ui @ui do
@runner.run(args)
end
assert_match(/WARNING: query command is deprecated. It will be removed in Rubygems [0-9]+/, @ui.error)
assert_match(/WARNING: It is recommended that you use `gem search` or `gem list` instead/, @ui.error)
end
def test_info_succeeds
args = %w[info]
use_ui @ui do
@runner.run(args)
end
assert_empty @ui.error
end
def test_list_succeeds
args = %w[list]
use_ui @ui do
@runner.run(args)
end
assert_empty @ui.error
end
def test_search_succeeds
args = %w[search]
use_ui @ui do
@runner.run(args)
end
assert_empty @ui.error
end
end