8000 Fix loading extra fields by hainesr · Pull Request #459 · rubyzip/rubyzip · GitHub
[go: up one dir, main page]

Skip to content

Fix loading extra fields #459

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 14, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Correctly read extra fields when opening a zip file.
Previously, only the extra fields stored in the central directory were
being read in. In reality it is often the case that the extra field in
the central directory is just a marker, and the full data is in the
local header. So we need to read both in and merge the two into the
final correct extra field. This merging infrastructure was already
implemented in the extra field code but we never actually read the
local extra fields in until now.

Reading the central directory headers and local entry headers seems
rather fragile, so we can't just read one over the other and hope to end
up with a correctly merged set of extra fields because this breaks other
things. So we need to specifically read the local extra field data and
merge just those bits.

This commit also fixes a couple of tests that were 'broken' by us now
reading extra fields in correctly!
  • Loading branch information
hainesr committed Oct 3, 2020
commit c2b9aa2893c03537e9a985b8410d9bb1eeeba8e2
29 changes: 28 additions & 1 deletion lib/zip/central_directory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,37 @@ def read_central_directory_entries(io) #:nodoc:
end
@entry_set = EntrySet.new
@size.times do
@entry_set << Entry.read_c_dir_entry(io)
entry = Entry.read_c_dir_entry(io)
next unless entry
< 8000 span class='blob-code-inner blob-code-marker ' data-code-marker="+">
offset = if entry.extra['Zip64']
entry.extra['Zip64'].relative_header_offset
else
entry.local_header_offset
end

unless offset.nil?
io_save = io.tell
io.seek(offset, IO::SEEK_SET)
entry.read_extra_field(read_local_extra_field(io))
io.seek(io_save, IO::SEEK_SET)
end

@entry_set << entry
end
end

def read_local_extra_field(io)
buf = io.read(::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH) || ''
return '' unless buf.bytesize == ::Zip::LOCAL_ENTRY_STATIC_HEADER_LENGTH

head, _, _, _, _, _, _, _, _, _, n_len, e_len = buf.unpack('VCCvvvvVVVvv')
return '' unless head == ::Zip::LOCAL_ENTRY_SIGNATURE

io.seek(n_len, IO::SEEK_CUR) # Skip over the entry name.
io.read(e_len)
end

def read_from_stream(io) #:nodoc:
buf = start_buf(io)
if zip64_file?(buf)
Expand Down
6 changes: 4 additions & 2 deletions test/filesystem/file_nonmutating_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,10 @@ def test_ctime
end

def test_atime
assert_nil(@zip_file.file.atime('file1'))
assert_nil(@zip_file.file.stat('file1').atime)
assert_equal(::Zip::DOSTime.at(1_027_694_306),
@zip_file.file.atime('file1'))
assert_equal(::Zip::DOSTime.at(1_027_694_306),
@zip_file.file.stat('file1').atime)
end

def test_ntfs_time
Expand Down
4 changes: 2 additions & 2 deletions test/filesystem/file_stat_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ def test_ino
end

def test_uid
assert_equal(0, @zip_file.file.stat('file1').uid)
assert_equal(500, @zip_file.file.stat('file1').uid)
end

def test_gid
assert_equal(0, @zip_file.file.stat('file1').gid)
assert_equal(500, @zip_file.file.stat('file1').gid)
end

def test_ftype
Expand Down
0