Only make directories writable when extracting.

This commit is contained in:
Markus Reiter 2023-02-21 12:36:58 +01:00
parent ebfc3996fd
commit 7a2aa85225
No known key found for this signature in database
GPG Key ID: 245293B51702655B
2 changed files with 49 additions and 6 deletions

View File

@ -28,13 +28,22 @@ describe UnpackStrategy do
context "when extracting a directory with nested directories" do
let(:directories) { "A/B/C" }
let(:executable) { "#{directories}/executable" }
let(:writable) { true }
let(:path) {
(mktmpdir/"file.tar").tap do |path|
mktmpdir do |dir|
Dir.mktmpdir do |dir|
dir = Pathname(dir)
(dir/directories).mkpath
FileUtils.chmod "-w", (dir/directories) unless writable
FileUtils.touch dir/executable
FileUtils.chmod 0555, dir/executable
FileUtils.chmod "-w", dir/directories unless writable
begin
system "tar", "--create", "--file", path, "--directory", dir, "A/"
ensure
FileUtils.chmod "+w", dir/directories unless writable
end
end
end
}
@ -53,6 +62,12 @@ describe UnpackStrategy do
expect(unpack_dir/directories).to be_writable
expect(unpack_dir/directories).not_to be_world_writable
end
it "does not make other files writable" do
strategy.extract_nestedly(to: unpack_dir)
expect(unpack_dir/executable).not_to be_writable
end
end
end

View File

@ -3,6 +3,27 @@
require "system_command"
# Helper module for iterating over directory trees.
#
# @api private
module PathnameEachDirectory
refine Pathname do
extend T::Sig
sig {
type_parameters(:T)
.params(
_block: T.proc.params(path: Pathname).returns(T.type_parameter(:T)),
).returns(T.type_parameter(:T))
}
def each_directory(&_block)
find do |path|
yield path if path.directory?
end
end
end
end
# Module containing all available strategies for unpacking archives.
#
# @api private
@ -12,6 +33,8 @@ module UnpackStrategy
include SystemCommand::Mixin
using PathnameEachDirectory
# Helper module for identifying the file type.
module Magic
# Length of the longest regex (currently Tar).
@ -164,15 +187,20 @@ module UnpackStrategy
children = tmp_unpack_dir.children
if children.count == 1 && !children.first.directory?
FileUtils.chmod "+rw", children.first, verbose: verbose
s = UnpackStrategy.detect(children.first, prioritize_extension: prioritize_extension)
s.extract_nestedly(to: to, verbose: verbose, prioritize_extension: prioritize_extension)
next
end
FileUtils.chmod_R "u+w", tmp_unpack_dir, force: true, verbose: verbose
# Ensure all extracted directories are writable.
tmp_unpack_dir.each_directory do |path|
next if path.writable?
FileUtils.chmod "u+w", path, verbose: verbose
end
Directory.new(tmp_unpack_dir).extract(to: to, verbose: verbose)
end
end