Skip Menu |

This queue is for tickets about the Archive-Zip CPAN distribution.

Report information
The Basics
Id: 42585
Status: new
Priority: 0/
Queue: Archive-Zip

People
Owner: Nobody in particular
Requestors: mtr_bcard [...] russotto.net
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 1.26
Fixed in: (no value)



Archive::Zip fails to read archives with more than $Archive::Zip::ChunkSize bytes of garbage after the end of directory signature. Attached is a modified version of _findEndOfCentralDirectory which fixes this issue, by reading blocks of ChunkSize bytes backwards from the end of the zipfile, rather than reading blocks of 512 bytes back to the ChunkSize.
Subject: eocd.pl
sub _findEndOfCentralDirectory { my $self = shift; my $fh = shift; my $data = ''; $fh->seek( 0, IO::Seekable::SEEK_END ) or return _ioError("seeking to end"); my $fileLength = $fh->tell(); if ( $fileLength < END_OF_CENTRAL_DIRECTORY_LENGTH + 4 ) { return _formatError("file is too short"); } my $seekOffset = 0; my $pos = -1; my $savedBytes = ""; for ( ; ; ) { $seekOffset += $Archive::Zip::ChunkSize; $seekOffset = $fileLength if ( $seekOffset > $fileLength ); $fh->seek( -$seekOffset, IO::Seekable::SEEK_END ) or return _ioError("seek failed"); my $bytesRead = $fh->read( $data, $Archive::Zip::ChunkSize ); if ( $bytesRead != $Archive::Zip::ChunkSize ) { return _ioError("read failed"); } $data .= $savedBytes; $pos = rindex( $data, END_OF_CENTRAL_DIRECTORY_SIGNATURE_STRING ); $savedbytes= substr $data,0, (END_OF_CENTRAL_DIRECTORY_LENGTH - 1); last if ( $pos >= 0 or $seekOffset == $fileLength ); } if ( $pos >= 0 ) { $fh->seek( $pos - $Archive::Zip::ChunkSize, IO::Seekable::SEEK_CUR ) or return _ioError("seeking to EOCD"); return AZ_OK; } else { return _formatError("can't find EOCD signature"); } }