diff options
| author | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2026-01-20 18:46:00 +0900 |
|---|---|---|
| committer | git <svn-admin@ruby-lang.org> | 2026-01-23 00:24:03 +0000 |
| commit | 13bb5599a45e15a19cd9e186bfa570fb39d68c73 (patch) | |
| tree | e0c7554cb87e17015ca54ae878dd404069d8f12e | |
| parent | 459222a4e2481ddb579247fb0338b52f13ce6c4c (diff) | |
[ruby/rubygems] Validate executable names for invalid characters
https://github.com/ruby/rubygems/commit/95dabef672
| -rw-r--r-- | lib/rubygems/specification_policy.rb | 8 | ||||
| -rw-r--r-- | test/rubygems/test_gem_specification.rb | 59 |
2 files changed, 67 insertions, 0 deletions
diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb index e5008a24db..0fcb635394 100644 --- a/lib/rubygems/specification_policy.rb +++ b/lib/rubygems/specification_policy.rb @@ -436,6 +436,7 @@ or set it to nil if you don't want to specify a license. warning "deprecated autorequire specified" if @specification.autorequire @specification.executables.each do |executable| + validate_executable(executable) validate_shebang_line_in(executable) end @@ -449,6 +450,13 @@ or set it to nil if you don't want to specify a license. warning("no #{attribute} specified") if value.nil? || value.empty? end + def validate_executable(executable) + separators = [File::SEPARATOR, File::ALT_SEPARATOR, File::PATH_SEPARATOR].compact.map {|sep| Regexp.escape(sep) }.join + return unless executable.match?(/[\s#{separators}]/) + + error "executable \"#{executable}\" contains invalid characters" + end + def validate_shebang_line_in(executable) executable_path = File.join(@specification.bindir, executable) return if File.read(executable_path, 2) == "#!" diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb index e8c2c0eb47..7675ade415 100644 --- a/test/rubygems/test_gem_specification.rb +++ b/test/rubygems/test_gem_specification.rb @@ -3013,6 +3013,65 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use: assert_match "#{w}: bin/exec is missing #! line\n", @ui.error, "error" end + def test_validate_executables_with_space + util_setup_validate + + FileUtils.mkdir_p File.join(@tempdir, "bin") + File.write File.join(@tempdir, "bin", "echo hax"), "#!/usr/bin/env ruby\n" + + @a1.executables = ["echo hax"] + + e = assert_raise Gem::InvalidSpecificationException do + use_ui @ui do + Dir.chdir @tempdir do + @a1.validate + end + end + end + + assert_match "executable \"echo hax\" contains invalid characters", e.message + end + + def test_validate_executables_with_path_separator + util_setup_validate + + FileUtils.mkdir_p File.join(@tempdir, "bin") + File.write File.join(@tempdir, "exe"), "#!/usr/bin/env ruby\n" + + @a1.executables = Gem.win_platform? ? ["..\\exe"] : ["../exe"] + + e = assert_raise Gem::InvalidSpecificationException do + use_ui @ui do + Dir.chdir @tempdir do + @a1.validate + end + end + end + + assert_match "executable \"#{Gem.win_platform? ? "..\\exe" : "../exe"}\" contains invalid characters", e.message + end + + def test_validate_executables_with_path_list_separator + sep = Gem.win_platform? ? ";" : ":" + + util_setup_validate + + FileUtils.mkdir_p File.join(@tempdir, "bin") + File.write File.join(@tempdir, "bin", "foo#{sep}bar"), "#!/usr/bin/env ruby\n" + + @a1.executables = ["foo#{sep}bar"] + + e = assert_raise Gem::InvalidSpecificationException do + use_ui @ui do + Dir.chdir @tempdir do + @a1.validate + end + end + end + + assert_match "executable \"foo#{sep}bar\" contains invalid characters", e.message + end + def test_validate_empty_require_paths util_setup_validate |
