diff options
Diffstat (limited to 'test/rubygems/test_gem_package.rb')
-rw-r--r-- | test/rubygems/test_gem_package.rb | 315 |
1 files changed, 220 insertions, 95 deletions
diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb index 9295f42dba..2065864107 100644 --- a/test/rubygems/test_gem_package.rb +++ b/test/rubygems/test_gem_package.rb @@ -189,7 +189,7 @@ class TestGemPackage < Gem::Package::TarTestCase File.symlink("code.rb", "lib/code_sym.rb") File.symlink("../lib/code.rb", "lib/code_sym2.rb") rescue Errno::EACCES => e - if win_platform? + if Gem.win_platform? pend "symlink - must be admin with no UAC on Windows" else raise e @@ -205,7 +205,8 @@ class TestGemPackage < Gem::Package::TarTestCase tar.rewind - files, symlinks = [], [] + files = [] + symlinks = [] Gem::Package::TarReader.new tar do |tar_io| tar_io.each_entry do |entry| @@ -286,8 +287,8 @@ class TestGemPackage < Gem::Package::TarTestCase assert_equal [PUBLIC_CERT.to_pem], reader.spec.cert_chain - assert_equal %w[metadata.gz metadata.gz.sig - data.tar.gz data.tar.gz.sig + assert_equal %w[metadata.gz metadata.gz.sig + data.tar.gz data.tar.gz.sig checksums.yaml.gz checksums.yaml.gz.sig], reader.files @@ -329,8 +330,8 @@ class TestGemPackage < Gem::Package::TarTestCase assert_equal [PUBLIC_CERT.to_pem], reader.spec.cert_chain - assert_equal %w[metadata.gz metadata.gz.sig - data.tar.gz data.tar.gz.sig + assert_equal %w[metadata.gz metadata.gz.sig + data.tar.gz data.tar.gz.sig checksums.yaml.gz checksums.yaml.gz.sig], reader.files @@ -392,8 +393,8 @@ class TestGemPackage < Gem::Package::TarTestCase assert_equal spec, reader.spec - assert_equal %w[metadata.gz metadata.gz.sig - data.tar.gz data.tar.gz.sig + assert_equal %w[metadata.gz metadata.gz.sig + data.tar.gz data.tar.gz.sig checksums.yaml.gz checksums.yaml.gz.sig], reader.files @@ -429,8 +430,8 @@ class TestGemPackage < Gem::Package::TarTestCase assert_equal spec, reader.spec - assert_equal %w[metadata.gz metadata.gz.sig - data.tar.gz data.tar.gz.sig + assert_equal %w[metadata.gz metadata.gz.sig + data.tar.gz data.tar.gz.sig checksums.yaml.gz checksums.yaml.gz.sig], reader.files @@ -441,11 +442,11 @@ class TestGemPackage < Gem::Package::TarTestCase data_tgz = util_tar_gz {} gem = util_tar do |tar| - tar.add_file "data.tar.gz", 0644 do |io| + tar.add_file "data.tar.gz", 0o644 do |io| io.write data_tgz.string end - tar.add_file "metadata.gz", 0644 do |io| + tar.add_file "metadata.gz", 0o644 do |io| Zlib::GzipWriter.wrap io do |gzio| gzio.write @spec.to_yaml end @@ -478,21 +479,21 @@ class TestGemPackage < Gem::Package::TarTestCase extracted = File.join @destination, "lib/code.rb" assert_path_exist extracted - mask = 0100666 & (~File.umask) + mask = 0o100666 & (~File.umask) assert_equal mask.to_s(8), File.stat(extracted).mode.to_s(8) unless - win_platform? + Gem.win_platform? end def test_extract_files_empty data_tgz = util_tar_gz {} gem = util_tar do |tar| - tar.add_file "data.tar.gz", 0644 do |io| + tar.add_file "data.tar.gz", 0o644 do |io| io.write data_tgz.string end - tar.add_file "metadata.gz", 0644 do |io| + tar.add_file "metadata.gz", 0o644 do |io| Zlib::GzipWriter.wrap io do |gzio| gzio.write @spec.to_yaml end @@ -510,11 +511,26 @@ class TestGemPackage < Gem::Package::TarTestCase assert_path_exist @destination end + def test_extract_file_permissions + pend "chmod not supported" if Gem.win_platform? + + gem_with_long_permissions = File.expand_path("packages/Bluebie-legs-0.6.2.gem", __dir__) + + package = Gem::Package.new gem_with_long_permissions + + package.extract_files @destination + + filepath = File.join @destination, "README.rdoc" + assert_path_exist filepath + + assert_equal 0o104444, File.stat(filepath).mode + end + def test_extract_tar_gz_absolute package = Gem::Package.new @gem tgz_io = util_tar_gz do |tar| - tar.add_file "/absolute.rb", 0644 do |io| + tar.add_file "/absolute.rb", 0o644 do |io| io.write "hi" end end @@ -523,7 +539,7 @@ class TestGemPackage < Gem::Package::TarTestCase package.extract_tar_gz tgz_io, @destination end - assert_equal("installing into parent path /absolute.rb of " + + assert_equal("installing into parent path /absolute.rb of " \ "#{@destination} is not allowed", e.message) end @@ -532,18 +548,18 @@ class TestGemPackage < Gem::Package::TarTestCase package.verify tgz_io = util_tar_gz do |tar| - tar.add_file "relative.rb", 0644 do |io| + tar.add_file "relative.rb", 0o644 do |io| io.write "hi" end - tar.mkdir "lib", 0755 - tar.add_symlink "lib/foo.rb", "../relative.rb", 0644 + tar.mkdir "lib", 0o755 + tar.add_symlink "lib/foo.rb", "../relative.rb", 0o644 end begin package.extract_tar_gz tgz_io, @destination rescue Errno::EACCES => e - if win_platform? + if Gem.win_platform? pend "symlink - must be admin with no UAC on Windows" else raise e @@ -558,13 +574,39 @@ class TestGemPackage < Gem::Package::TarTestCase File.read(extracted) end + def test_extract_symlink_into_symlink_dir + package = Gem::Package.new @gem + tgz_io = util_tar_gz do |tar| + tar.mkdir "lib", 0o755 + tar.add_symlink "lib/link", "./inside.rb", 0o644 + tar.add_file "lib/inside.rb", 0o644 do |io| + io.write "hi" + end + end + + destination_subdir = File.join @destination, "subdir" + FileUtils.mkdir_p destination_subdir + + destination_linkdir = File.join @destination, "linkdir" + File.symlink(destination_subdir, destination_linkdir) + + package.extract_tar_gz tgz_io, destination_linkdir + + extracted = File.join destination_subdir, "lib/link" + assert_path_exist extracted + assert_equal "./inside.rb", + File.readlink(extracted) + assert_equal "hi", + File.read(extracted) + end + def test_extract_tar_gz_symlink_broken_relative_path package = Gem::Package.new @gem package.verify tgz_io = util_tar_gz do |tar| - tar.mkdir "lib", 0755 - tar.add_symlink "lib/foo.rb", "../broken.rb", 0644 + tar.mkdir "lib", 0o755 + tar.add_symlink "lib/foo.rb", "../broken.rb", 0o644 end ui = Gem::MockGemUi.new @@ -583,9 +625,9 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem tgz_io = util_tar_gz do |tar| - tar.mkdir "lib", 0755 - tar.add_symlink "lib/link", "../..", 0644 - tar.add_file "lib/link/outside.txt", 0644 do |io| + tar.mkdir "lib", 0o755 + tar.add_symlink "lib/link", "../..", 0o644 + tar.add_file "lib/link/outside.txt", 0o644 do |io| io.write "hi" end end @@ -596,7 +638,7 @@ class TestGemPackage < Gem::Package::TarTestCase destination_subdir = File.join @destination, "subdir" FileUtils.mkdir_p destination_subdir - expected_exceptions = win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError] + expected_exceptions = Gem.win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError] e = assert_raise(*expected_exceptions) do package.extract_tar_gz tgz_io, destination_subdir @@ -604,7 +646,7 @@ class TestGemPackage < Gem::Package::TarTestCase pend "symlink - must be admin with no UAC on Windows" if Errno::EACCES === e - assert_equal("installing symlink 'lib/link' pointing to parent path #{@destination} of " + + assert_equal("installing symlink 'lib/link' pointing to parent path #{@destination} of " \ "#{destination_subdir} is not allowed", e.message) assert_path_not_exist File.join(@destination, "outside.txt") @@ -627,11 +669,11 @@ class TestGemPackage < Gem::Package::TarTestCase pend "TMPDIR seems too long to add it as symlink into tar" if destination_user_dir.size > 90 tgz_io = util_tar_gz do |tar| - tar.add_symlink "link", destination_user_dir, 16877 - tar.add_symlink "link/dir", ".", 16877 + tar.add_symlink "link", destination_user_dir, 16_877 + tar.add_symlink "link/dir", ".", 16_877 end - expected_exceptions = win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError] + expected_exceptions = Gem.win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError] e = assert_raise(*expected_exceptions) do package.extract_tar_gz tgz_io, destination_subdir @@ -639,7 +681,7 @@ class TestGemPackage < Gem::Package::TarTestCase pend "symlink - must be admin with no UAC on Windows" if Errno::EACCES === e - assert_equal("installing symlink 'link' pointing to parent path #{destination_user_dir} of " + + assert_equal("installing symlink 'link' pointing to parent path #{destination_user_dir} of " \ "#{destination_subdir} is not allowed", e.message) assert_path_exist destination_user_subdir @@ -651,11 +693,11 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem tgz_io = util_tar_gz do |tar| - tar.mkdir "lib", 0755 - tar.add_file "lib/foo.rb", 0644 do |io| + tar.mkdir "lib", 0o755 + tar.add_file "lib/foo.rb", 0o644 do |io| io.write "hi" end - tar.mkdir "lib/foo", 0755 + tar.mkdir "lib/foo", 0o755 end package.extract_tar_gz tgz_io, @destination @@ -671,7 +713,7 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem tgz_io = util_tar_gz do |tar| - tar.add_file "./dot_slash.rb", 0644 do |io| + tar.add_file "./dot_slash.rb", 0o644 do |io| io.write "hi" end end @@ -686,7 +728,7 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem tgz_io = util_tar_gz do |tar| - tar.add_file ".dot_file.rb", 0644 do |io| + tar.add_file ".dot_file.rb", 0o644 do |io| io.write "hi" end end @@ -702,7 +744,7 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem tgz_io = util_tar_gz do |tar| - tar.add_file "foo/file.rb", 0644 do |io| + tar.add_file "foo/file.rb", 0o644 do |io| io.write "hi" end end @@ -718,12 +760,10 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem file = "file.rb".dup - file.taint if RUBY_VERSION < "2.7" destination = package.install_location file, @destination assert_equal File.join(@destination, "file.rb"), destination - refute destination.tainted? if RUBY_VERSION < "2.7" end def test_install_location_absolute @@ -733,7 +773,7 @@ class TestGemPackage < Gem::Package::TarTestCase package.install_location "/absolute.rb", @destination end - assert_equal("installing into parent path /absolute.rb of " + + assert_equal("installing into parent path /absolute.rb of " \ "#{@destination} is not allowed", e.message) end @@ -757,12 +797,10 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new @gem file = "foo//file.rb".dup - file.taint if RUBY_VERSION < "2.7" destination = package.install_location file, @destination assert_equal File.join(@destination, "foo", "file.rb"), destination - refute destination.tainted? if RUBY_VERSION < "2.7" end def test_install_location_relative @@ -774,7 +812,7 @@ class TestGemPackage < Gem::Package::TarTestCase parent = File.expand_path File.join @destination, "../relative.rb" - assert_equal("installing into parent path #{parent} of " + + assert_equal("installing into parent path #{parent} of " \ "#{@destination} is not allowed", e.message) end @@ -789,13 +827,15 @@ class TestGemPackage < Gem::Package::TarTestCase parent = File.expand_path File.join @destination, filename - assert_equal("installing into parent path #{parent} of " + + assert_equal("installing into parent path #{parent} of " \ "#{@destination} is not allowed", e.message) end def test_load_spec entry = StringIO.new Gem::Util.gzip @spec.to_yaml - def entry.full_name() "metadata.gz" end + def entry.full_name + "metadata.gz" + end package = Gem::Package.new "nonexistent.gem" @@ -816,7 +856,7 @@ class TestGemPackage < Gem::Package::TarTestCase def test_verify_checksum_bad data_tgz = util_tar_gz do |tar| - tar.add_file "lib/code.rb", 0444 do |io| + tar.add_file "lib/code.rb", 0o444 do |io| io.write "# lib/code.rb" end end @@ -826,11 +866,11 @@ class TestGemPackage < Gem::Package::TarTestCase gem = util_tar do |tar| metadata_gz = Gem::Util.gzip @spec.to_yaml - tar.add_file "metadata.gz", 0444 do |io| + tar.add_file "metadata.gz", 0o444 do |io| io.write metadata_gz end - tar.add_file "data.tar.gz", 0444 do |io| + tar.add_file "data.tar.gz", 0o444 do |io| io.write data_tgz end @@ -840,7 +880,7 @@ class TestGemPackage < Gem::Package::TarTestCase "metadata.gz" => "bogus", }, } - tar.add_file "checksums.yaml.gz", 0444 do |io| + tar.add_file "checksums.yaml.gz", 0o444 do |io| Zlib::GzipWriter.wrap io do |gz_io| gz_io.write Psych.dump bogus_checksums end @@ -863,7 +903,7 @@ class TestGemPackage < Gem::Package::TarTestCase def test_verify_checksum_missing data_tgz = util_tar_gz do |tar| - tar.add_file "lib/code.rb", 0444 do |io| + tar.add_file "lib/code.rb", 0o444 do |io| io.write "# lib/code.rb" end end @@ -873,7 +913,7 @@ class TestGemPackage < Gem::Package::TarTestCase gem = util_tar do |tar| metadata_gz = Gem::Util.gzip @spec.to_yaml - tar.add_file "metadata.gz", 0444 do |io| + tar.add_file "metadata.gz", 0o444 do |io| io.write metadata_gz end @@ -886,13 +926,13 @@ class TestGemPackage < Gem::Package::TarTestCase }, } - tar.add_file "checksums.yaml.gz", 0444 do |io| + tar.add_file "checksums.yaml.gz", 0o444 do |io| Zlib::GzipWriter.wrap io do |gz_io| gz_io.write Psych.dump checksums end end - tar.add_file "data.tar.gz", 0444 do |io| + tar.add_file "data.tar.gz", 0o444 do |io| io.write data_tgz end end @@ -911,7 +951,7 @@ class TestGemPackage < Gem::Package::TarTestCase tf = Tempfile.open "corrupt" do |io| data = Gem::Util.gzip "a" * 10 io.write \ - tar_file_header("metadata.gz", "\000x", 0644, data.length, Time.now) + tar_file_header("metadata.gz", "\000x", 0o644, data.length, Time.now) io.write data io.rewind @@ -928,6 +968,95 @@ class TestGemPackage < Gem::Package::TarTestCase tf.close! end + def test_verify_corrupt_tar_metadata_entry + gem = tar_file_header("metadata.gz", "", 0, 999, Time.now) + + File.open "corrupt.gem", "wb" do |io| + io.write gem + end + + package = Gem::Package.new "corrupt.gem" + + e = nil + out_err = capture_output do + e = assert_raise Gem::Package::FormatError do + package.verify + end + end + + assert_match(/(EOFError|end of file reached) in corrupt.gem/i, e.message) + assert_equal(["", "Exception while verifying corrupt.gem\n"], out_err) + end + + def test_verify_corrupt_tar_checksums_entry + gem = tar_file_header("checksums.yaml.gz", "", 0, 100, Time.now) + + File.open "corrupt.gem", "wb" do |io| + io.write gem + end + + package = Gem::Package.new "corrupt.gem" + + e = assert_raise Gem::Package::FormatError do + package.verify + end + + assert_equal "not in gzip format in corrupt.gem", e.message + end + + def test_verify_corrupt_tar_data_entry + gem = tar_file_header("data.tar.gz", "", 0, 100, Time.now) + + File.open "corrupt.gem", "wb" do |io| + io.write gem + end + + package = Gem::Package.new "corrupt.gem" + + e = nil + out_err = capture_output do + e = assert_raise Gem::Package::FormatError do + package.verify + end + end + + assert_match(/(EOFError|end of file reached) in corrupt.gem/i, e.message) + assert_equal(["", "Exception while verifying corrupt.gem\n"], out_err) + end + + def test_corrupt_data_tar_gz + data_tgz = util_gzip tar_file_header("lib/code.rb", "", 0, 100, Time.now) + metadata_gz = util_gzip @spec.to_yaml + + gem = util_tar do |tar| + tar.add_file "data.tar.gz", 0o444 do |io| + io.write data_tgz + end + + tar.add_file "metadata.gz", 0o644 do |io| + io.write metadata_gz + end + end + + File.open "corrupt.gem", "wb" do |io| + io.write gem.string + end + + package = Gem::Package.new "corrupt.gem" + + e = assert_raise Gem::Package::FormatError do + package.contents + end + + assert_match(/(EOFError|end of file reached) in corrupt.gem/i, e.message) + + e = assert_raise Gem::Package::FormatError do + package.extract_files @destination + end + + assert_match(/(EOFError|end of file reached) in corrupt.gem/i, e.message) + end + def test_verify_empty FileUtils.touch "empty.gem" @@ -947,8 +1076,8 @@ class TestGemPackage < Gem::Package::TarTestCase package.verify end - assert_match %r{^No such file or directory}, e.message - assert_match %r{nonexistent.gem$}, e.message + assert_match(/^No such file or directory/, e.message) + assert_match(/nonexistent.gem$/, e.message) end def test_verify_duplicate_file @@ -963,8 +1092,8 @@ class TestGemPackage < Gem::Package::TarTestCase build.add_metadata gem build.add_contents gem - gem.add_file_simple "a.sig", 0444, 0 - gem.add_file_simple "a.sig", 0444, 0 + gem.add_file_simple "a.sig", 0o444, 0 + gem.add_file_simple "a.sig", 0o444, 0 end end @@ -1035,12 +1164,23 @@ class TestGemPackage < Gem::Package::TarTestCase # write bogus data.tar.gz to foil signature bogus_data = Gem::Util.gzip "hello" fake_signer = Class.new do - def digest_name; "SHA512"; end - def digest_algorithm; OpenSSL::Digest(:SHA512).new; end - def key; "key"; end - def sign(*); "fake_sig"; end + def digest_name + "SHA512" + end + + def digest_algorithm + OpenSSL::Digest(:SHA512).new + end + + def key + "key" + end + + def sign(*) + "fake_sig" + end end - gem.add_file_signed "data2.tar.gz", 0444, fake_signer.new do |io| + gem.add_file_signed "data2.tar.gz", 0o444, fake_signer.new do |io| io.write bogus_data end @@ -1082,7 +1222,9 @@ class TestGemPackage < Gem::Package::TarTestCase def test_verify_entry entry = Object.new - def entry.full_name() raise ArgumentError, "whatever" end + def entry.full_name + raise ArgumentError, "whatever" + end package = Gem::Package.new @gem @@ -1109,11 +1251,15 @@ class TestGemPackage < Gem::Package::TarTestCase $good_name = vm entry = Object.new - def entry.full_name() $good_name end + def entry.full_name + $good_name + end package = Gem::Package.new(@gem) package.instance_variable_set(:@files, []) - def package.load_spec(entry) $spec_loaded = true end + def package.load_spec(entry) + $spec_loaded = true + end package.verify_entry(entry) @@ -1126,11 +1272,15 @@ class TestGemPackage < Gem::Package::TarTestCase $bad_name = vm entry = Object.new - def entry.full_name() $bad_name end + def entry.full_name + $bad_name + end package = Gem::Package.new(@gem) package.instance_variable_set(:@files, []) - def package.load_spec(entry) $spec_loaded = true end + def package.load_spec(entry) + $spec_loaded = true + end package.verify_entry(entry) @@ -1172,29 +1322,4 @@ class TestGemPackage < Gem::Package::TarTestCase assert_equal %w[lib/code.rb], package.contents end - - def util_tar - tar_io = StringIO.new - - Gem::Package::TarWriter.new tar_io do |tar| - yield tar - end - - tar_io.rewind - - tar_io - end - - def util_tar_gz(&block) - tar_io = util_tar(&block) - - tgz_io = StringIO.new - - # can't wrap TarWriter because it seeks - Zlib::GzipWriter.wrap tgz_io do |io| - io.write tar_io.string - end - - StringIO.new tgz_io.string - end end |