Skip to content

Commit

Permalink
Ensure File.open applies default umask on gem extract
Browse files Browse the repository at this point in the history
  • Loading branch information
martinemde committed Dec 17, 2023
1 parent f4868c6 commit 388fb83
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 6 deletions.
8 changes: 5 additions & 3 deletions lib/rubygems/package.rb
Expand Up @@ -448,13 +448,15 @@ def extract_tar_gz(io, destination_dir, pattern = "*") # :nodoc:
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| out.write entry.read }
FileUtils.chmod file_mode(entry.header.mode), destination
File.open(destination, "wb", file_mode(entry.header.mode)) {|out| out.write entry.read }
end

verbose destination
Expand Down
8 changes: 6 additions & 2 deletions test/rubygems/test_gem.rb
Expand Up @@ -161,13 +161,17 @@ def assert_self_install_permissions(format_executable: false)
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|
Expand All @@ -180,7 +184,7 @@ def assert_self_install_permissions(format_executable: false)

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 = {
Expand Down
37 changes: 36 additions & 1 deletion test/rubygems/test_gem_package.rb
Expand Up @@ -523,7 +523,42 @@ def test_extract_file_permissions
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
Expand Down

0 comments on commit 388fb83

Please sign in to comment.