summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Emde <martin.emde@gmail.com>2023-12-17 13:22:38 -0800
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2024-01-24 13:50:16 +0900
commit01f9766aa05182a7bbdc914a5dcd8a36ebade861 (patch)
treea93628420b1a39603f4be3bb31b83a45feb09d22
parent2defa9f4ae52c99e64a02b7f78362fbd788a1fd0 (diff)
Ensure File.open applies default umask on gem extract
-rw-r--r--lib/rubygems/package.rb8
-rw-r--r--test/rubygems/test_gem.rb8
-rw-r--r--test/rubygems/test_gem_package.rb37
3 files changed, 47 insertions, 6 deletions
diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb
index 387e40ffd7..7b4cab7964 100644
--- a/lib/rubygems/package.rb
+++ b/lib/rubygems/package.rb
@@ -448,13 +448,15 @@ EOM
end
unless directories.include?(mkdir)
- FileUtils.mkdir_p mkdir, mode: dir_mode ? 0o755 : (entry.header.mode if entry.directory?)
+ mkdir_mode = 0o755 if dir_mode
+ mkdir_mode ||= entry.header.mode if entry.directory?
+ mkdir_mode &= ~File.umask if mkdir_mode
+ FileUtils.mkdir_p mkdir, mode: mkdir_mode
directories << mkdir
end
if entry.file?
- File.open(destination, "wb") {|out| copy_stream(entry, out) }
- FileUtils.chmod file_mode(entry.header.mode), destination
+ File.open(destination, "wb", file_mode(entry.header.mode)) {|out| copy_stream(entry, out) }
end
verbose destination
diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb
index d4c307978e..8dc8563aaf 100644
--- a/test/rubygems/test_gem.rb
+++ b/test/rubygems/test_gem.rb
@@ -161,13 +161,17 @@ class TestGem < Gem::TestCase
format_executable: format_executable,
}
Dir.chdir @tempdir do
+ # use chmod to set global permissions (so umask doesn't bypass our choice) to ensure they are masked on install
Dir.mkdir "bin"
+ File.chmod 0o777, "bin"
Dir.mkdir "data"
+ File.chmod 0o777, "data"
File.write "bin/foo", "#!/usr/bin/env ruby\n"
- File.chmod 0o755, "bin/foo"
+ File.chmod 0o777, "bin/foo"
File.write "data/foo.txt", "blah\n"
+ File.chmod 0o666, "data/foo.txt"
spec_fetcher do |f|
f.gem "foo", 1 do |s|
@@ -180,7 +184,7 @@ class TestGem < Gem::TestCase
prog_mode = (options[:prog_mode] & mask).to_s(8)
dir_mode = (options[:dir_mode] & mask).to_s(8)
- data_mode = (options[:data_mode] & mask).to_s(8)
+ data_mode = (options[:data_mode] & mask & (~File.umask)).to_s(8)
prog_name = "foo"
prog_name = RbConfig::CONFIG["ruby_install_name"].sub("ruby", "foo") if options[:format_executable]
expected = {
diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb
index 2065864107..7adbc695ec 100644
--- a/test/rubygems/test_gem_package.rb
+++ b/test/rubygems/test_gem_package.rb
@@ -523,7 +523,42 @@ class TestGemPackage < Gem::Package::TarTestCase
filepath = File.join @destination, "README.rdoc"
assert_path_exist filepath
- assert_equal 0o104444, File.stat(filepath).mode
+ assert_equal 0o100444.to_s(8), File.stat(filepath).mode.to_s(8)
+ end
+
+ def test_extract_file_umask_global_permissions
+ pend "chmod not supported" if Gem.win_platform?
+
+ package = Gem::Package.new @gem
+
+ tgz_io = util_tar_gz do |tar|
+ tar.mkdir "lib", 0o777
+ tar.add_file "bin/global", 0o777 do |io|
+ io.write "#!/bin/ruby\nputs 'hello world'"
+ end
+ tar.add_file "lib/global.rb", 0o666 do |io|
+ io.write "puts 'hello world'"
+ end
+ end
+
+ package.extract_tar_gz tgz_io, @destination
+
+ dirpath = File.join @destination, "lib"
+ assert_path_exist dirpath
+ mode = 0o40755 & (~File.umask)
+ assert_equal mode.to_s(8), File.stat(dirpath).mode.to_s(8)
+
+ filepath = File.join @destination, "lib", "global.rb"
+ assert_path_exist filepath
+ assert_equal "puts 'hello world'", File.read(filepath)
+ mode = 0o100644 & (~File.umask)
+ assert_equal mode.to_s(8), File.stat(filepath).mode.to_s(8)
+
+ filepath = File.join @destination, "bin", "global"
+ assert_path_exist filepath
+ assert_equal "#!/bin/ruby\nputs 'hello world'", File.read(filepath)
+ mode = 0o100755 & (~File.umask)
+ assert_equal mode.to_s(8), File.stat(filepath).mode.to_s(8)
end
def test_extract_tar_gz_absolute