diff --git a/lib/zip/central_directory.rb b/lib/zip/central_directory.rb index d54e567..e8c20cf 100644 --- a/lib/zip/central_directory.rb +++ b/lib/zip/central_directory.rb @@ -149,11 +149,16 @@ module Zip end def read_central_directory_entries(io) #:nodoc: + # `StringIO` doesn't raise `EINVAL` if you seek beyond the current end, + # so we need to catch that *and* query `io#eof?` here. + eof = false begin io.seek(@cdir_offset, IO::SEEK_SET) rescue Errno::EINVAL - raise Error, 'Zip consistency problem while reading central directory entry' + eof = true end + raise Error, 'Zip consistency problem while reading central directory entry' if eof || io.eof? + @entry_set = EntrySet.new @size.times do entry = Entry.read_c_dir_entry(io) diff --git a/test/central_directory_test.rb b/test/central_directory_test.rb index 011bdb5..afe2156 100644 --- a/test/central_directory_test.rb +++ b/test/central_directory_test.rb @@ -26,15 +26,22 @@ class ZipCentralDirectoryTest < MiniTest::Test rescue ::Zip::Error end - def test_read_from_truncated_zip_file - fragment = '' - File.open('test/data/testDirectory.bin', 'rb') { |f| fragment = f.read } - fragment.slice!(12) # removed part of first cdir entry. eocd structure still complete - fragment.extend(IOizeString) - entry = ::Zip::CentralDirectory.new - entry.read_from_stream(fragment) - raise 'ZipError expected' - rescue ::Zip::Error + def test_read_eocd_with_wrong_cdir_offset_from_file + ::File.open('test/data/testDirectory.bin', 'rb') do |f| + assert_raises(::Zip::Error) do + cdir = ::Zip::CentralDirectory.new + cdir.read_from_stream(f) + end + end + end + + def test_read_eocd_with_wrong_cdir_offset_from_buffer + ::File.open('test/data/testDirectory.bin', 'rb') do |f| + assert_raises(::Zip::Error) do + cdir = ::Zip::CentralDirectory.new + cdir.read_from_stream(StringIO.new(f.read)) + end + end end def test_write_to_stream