[rubygems/rubygems] Don't try to remove previous install folder if it's empty

Ruby ships with empty directories for default gems. If Ruby
installations has unsafe world-writable permissions, we will complain
when about to install a gem that happens to be also a default gem,
because we'll start by removing the previous install folder and that's
supposed to be insecure due to too loose permissions.

However, if the folder is empty, we don't actually need to remove
anything, so we can skip the whole thing, avoiding the errors.

https://github.com/rubygems/rubygems/commit/2f3cd8ac4e
This commit is contained in:
David Rodríguez 2024-08-30 18:57:20 +02:00 committed by git
parent b00b0d5f8f
commit bb511c3f10
2 changed files with 29 additions and 0 deletions

View File

@ -150,6 +150,7 @@ module Bundler
def strict_rm_rf(dir)
return unless File.exist?(dir)
return if Dir.empty?(dir)
parent = File.dirname(dir)
parent_st = File.stat(parent)

View File

@ -1059,6 +1059,34 @@ RSpec.describe "bundle install with gem sources" do
end
end
describe "when gems path is world writable (no sticky bit set), but previous install is just an empty dir (like it happens with default gems)", :permissions do
let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") }
let(:full_path) { gems_path.join("foo-1.0.0") }
before do
build_repo4 do
build_gem "foo", "1.0.0" do |s|
s.write "CHANGELOG.md", "foo"
end
end
gemfile <<-G
source "https://gem.repo4"
gem 'foo'
G
end
it "does not try to remove the directory and thus don't abort with an error about unsafe directory removal" do
bundle "config set --local path vendor"
FileUtils.mkdir_p(gems_path)
FileUtils.chmod(0o777, gems_path)
Dir.mkdir(full_path)
bundle "install"
end
end
describe "when bundle cache path does not have write access", :permissions do
let(:cache_path) { bundled_app("vendor/#{Bundler.ruby_scope}/cache") }