summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2026-01-20 18:46:00 +0900
committergit <svn-admin@ruby-lang.org>2026-01-23 00:24:03 +0000
commit13bb5599a45e15a19cd9e186bfa570fb39d68c73 (patch)
treee0c7554cb87e17015ca54ae878dd404069d8f12e
parent459222a4e2481ddb579247fb0338b52f13ce6c4c (diff)
[ruby/rubygems] Validate executable names for invalid characters
https://github.com/ruby/rubygems/commit/95dabef672
-rw-r--r--lib/rubygems/specification_policy.rb8
-rw-r--r--test/rubygems/test_gem_specification.rb59
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