Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 2 additions & 19 deletions lib/rubygems/package.rb
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@ def normalize_path(pathname) # :nodoc:
##
# Loads a Gem::Specification from the TarEntry +entry+

def load_spec(entry) # :nodoc:
def load_spec_from_metadata(entry) # :nodoc:
limit = 10 * 1024 * 1024
case entry.full_name
when "metadata" then
Expand Down Expand Up @@ -678,12 +678,7 @@ def verify_entry(entry)
digest entry
end

case file_name
when "metadata", "metadata.gz" then
load_spec entry
when "data.tar.gz" then
verify_gz entry
end
load_spec_from_metadata entry
rescue StandardError
warn "Exception while verifying #{@gem.path}"
raise
Expand Down Expand Up @@ -711,18 +706,6 @@ def verify_files(gem)
end
end

##
# Verifies that +entry+ is a valid gzipped file.

def verify_gz(entry) # :nodoc:
Zlib::GzipReader.wrap entry do |gzio|
# TODO: read into a buffer once zlib supports it
gzio.read 16_384 until gzio.eof? # gzip checksum verification
Copy link
Contributor

@Edouard-chin Edouard-chin Nov 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that we read until EOF because that's when the GZipReader will verify the gzip checksum header against the decompressed data. I read that from the doc https://docs.ruby-lang.org/en/3.4/Zlib/GzipReader.html

When an reading request is received beyond the end of file (the end of compressed data). That is, when Zlib::GzipReader#read [...] reading returns nil.

Are we still reading at eof anywhere else so that the checksum verification is still performed?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rubygems.org currently depends on this code to validate gems being pushed. Talking with Arron this morning, it should be fairly trivial 🤞🏻 to move, but I wanted to highlight this so any changes can be coordinated between the two projects.

end
rescue Zlib::GzipFile::Error => e
raise Gem::Package::FormatError.new(e.message, entry.full_name)
end

if RUBY_ENGINE == "truffleruby"
def copy_stream(src, dst, size) # :nodoc:
dst.write src.read(size)
Expand Down
4 changes: 2 additions & 2 deletions test/rubygems/test_gem_package.rb
Original file line number Diff line number Diff line change
Expand Up @@ -858,15 +858,15 @@ def test_install_location_suffix
"#{@destination} is not allowed", e.message)
end

def test_load_spec
def test_load_spec_from_metadata
entry = StringIO.new Gem::Util.gzip @spec.to_yaml
def entry.full_name
"metadata.gz"
end

package = Gem::Package.new "nonexistent.gem"

spec = package.load_spec entry
spec = package.load_spec_from_metadata entry

assert_equal @spec, spec
end
Expand Down