Skip to content

Commit 01f9766

Browse files
martinemdehsbt
authored andcommitted
Ensure File.open applies default umask on gem extract
1 parent 2defa9f commit 01f9766

File tree

3 files changed

+47
-6
lines changed

3 files changed

+47
-6
lines changed

lib/rubygems/package.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,13 +448,15 @@ def extract_tar_gz(io, destination_dir, pattern = "*") # :nodoc:
448448
end
449449

450450
unless directories.include?(mkdir)
451-
FileUtils.mkdir_p mkdir, mode: dir_mode ? 0o755 : (entry.header.mode if entry.directory?)
451+
mkdir_mode = 0o755 if dir_mode
452+
mkdir_mode ||= entry.header.mode if entry.directory?
453+
mkdir_mode &= ~File.umask if mkdir_mode
454+
FileUtils.mkdir_p mkdir, mode: mkdir_mode
452455
directories << mkdir
453456
end
454457

455458
if entry.file?
456-
File.open(destination, "wb") {|out| copy_stream(entry, out) }
457-
FileUtils.chmod file_mode(entry.header.mode), destination
459+
File.open(destination, "wb", file_mode(entry.header.mode)) {|out| copy_stream(entry, out) }
458460
end
459461

460462
verbose destination

test/rubygems/test_gem.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,13 +161,17 @@ def assert_self_install_permissions(format_executable: false)
161161
format_executable: format_executable,
162162
}
163163
Dir.chdir @tempdir do
164+
# use chmod to set global permissions (so umask doesn't bypass our choice) to ensure they are masked on install
164165
Dir.mkdir "bin"
166+
File.chmod 0o777, "bin"
165167
Dir.mkdir "data"
168+
File.chmod 0o777, "data"
166169

167170
File.write "bin/foo", "#!/usr/bin/env ruby\n"
168-
File.chmod 0o755, "bin/foo"
171+
File.chmod 0o777, "bin/foo"
169172

170173
File.write "data/foo.txt", "blah\n"
174+
File.chmod 0o666, "data/foo.txt"
171175

172176
spec_fetcher do |f|
173177
f.gem "foo", 1 do |s|
@@ -180,7 +184,7 @@ def assert_self_install_permissions(format_executable: false)
180184

181185
prog_mode = (options[:prog_mode] & mask).to_s(8)
182186
dir_mode = (options[:dir_mode] & mask).to_s(8)
183-
data_mode = (options[:data_mode] & mask).to_s(8)
187+
data_mode = (options[:data_mode] & mask & (~File.umask)).to_s(8)
184188
prog_name = "foo"
185189
prog_name = RbConfig::CONFIG["ruby_install_name"].sub("ruby", "foo") if options[:format_executable]
186190
expected = {

test/rubygems/test_gem_package.rb

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,42 @@ def test_extract_file_permissions
523523
filepath = File.join @destination, "README.rdoc"
524524
assert_path_exist filepath
525525

526-
assert_equal 0o104444, File.stat(filepath).mode
526+
assert_equal 0o100444.to_s(8), File.stat(filepath).mode.to_s(8)
527+
end
528+
529+
def test_extract_file_umask_global_permissions
530+
pend "chmod not supported" if Gem.win_platform?
531+
532+
package = Gem::Package.new @gem
533+
534+
tgz_io = util_tar_gz do |tar|
535+
tar.mkdir "lib", 0o777
536+
tar.add_file "bin/global", 0o777 do |io|
537+
io.write "#!/bin/ruby\nputs 'hello world'"
538+
end
539+
tar.add_file "lib/global.rb", 0o666 do |io|
540+
io.write "puts 'hello world'"
541+
end
542+
end
543+
544+
package.extract_tar_gz tgz_io, @destination
545+
546+
dirpath = File.join @destination, "lib"
547+
assert_path_exist dirpath
548+
mode = 0o40755 & (~File.umask)
549+
assert_equal mode.to_s(8), File.stat(dirpath).mode.to_s(8)
550+
551+
filepath = File.join @destination, "lib", "global.rb"
552+
assert_path_exist filepath
553+
assert_equal "puts 'hello world'", File.read(filepath)
554+
mode = 0o100644 & (~File.umask)
555+
assert_equal mode.to_s(8), File.stat(filepath).mode.to_s(8)
556+
557+
filepath = File.join @destination, "bin", "global"
558+
assert_path_exist filepath
559+
assert_equal "#!/bin/ruby\nputs 'hello world'", File.read(filepath)
560+
mode = 0o100755 & (~File.umask)
561+
assert_equal mode.to_s(8), File.stat(filepath).mode.to_s(8)
527562
end
528563

529564
def test_extract_tar_gz_absolute

0 commit comments

Comments
 (0)