Merge r407,r508 from libarchive.googlecode.com: Correctly handle

Zip entries that are zero length but stored with deflate.  This
is arguably a silly thing to do (deflating a zero-length file actually
makes it bigger) but apparently quite a few Zip writers do this.
This was broken in two places:  archive_write_disk disliked being asked
to write data to zero-length files (even if the write was zero-length)
and zip_read_file_header tripped over itself when non-regular files
had compressed bodies.
This commit is contained in:
Tim Kientzle 2009-03-06 04:50:39 +00:00
parent 43a8e5f098
commit 17fcda1a0b
2 changed files with 44 additions and 44 deletions

View File

@ -75,7 +75,6 @@ struct zip {
/* Flags to mark progress of decompression. */
char decompress_init;
char end_of_entry;
char end_of_entry_cleanup;
unsigned long crc32;
ssize_t filename_length;
@ -298,7 +297,6 @@ archive_read_format_zip_read_header(struct archive_read *a,
zip = (struct zip *)(a->format->data);
zip->decompress_init = 0;
zip->end_of_entry = 0;
zip->end_of_entry_cleanup = 0;
zip->entry_uncompressed_bytes_read = 0;
zip->entry_compressed_bytes_read = 0;
zip->entry_crc32 = crc32(0, NULL, 0);
@ -373,7 +371,7 @@ archive_read_format_zip_read_header(struct archive_read *a,
return (ARCHIVE_FATAL);
}
int
static int
zip_read_file_header(struct archive_read *a, struct archive_entry *entry,
struct zip *zip)
{
@ -499,45 +497,6 @@ archive_read_format_zip_read_data(struct archive_read *a,
* ARCHIVE_EOF this time.
*/
if (zip->end_of_entry) {
if (!zip->end_of_entry_cleanup) {
if (zip->flags & ZIP_LENGTH_AT_END) {
const char *p;
if ((p = __archive_read_ahead(a, 16, NULL)) == NULL) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP end-of-file record");
return (ARCHIVE_FATAL);
}
zip->crc32 = archive_le32dec(p + 4);
zip->compressed_size = archive_le32dec(p + 8);
zip->uncompressed_size = archive_le32dec(p + 12);
__archive_read_consume(a, 16);
}
/* Check file size, CRC against these values. */
if (zip->compressed_size != zip->entry_compressed_bytes_read) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"ZIP compressed data is wrong size");
return (ARCHIVE_WARN);
}
/* Size field only stores the lower 32 bits of the actual size. */
if ((zip->uncompressed_size & UINT32_MAX)
!= (zip->entry_uncompressed_bytes_read & UINT32_MAX)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"ZIP uncompressed data is wrong size");
return (ARCHIVE_WARN);
}
/* Check computed CRC against header */
if (zip->crc32 != zip->entry_crc32) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"ZIP bad CRC: 0x%lx should be 0x%lx",
zip->entry_crc32, zip->crc32);
return (ARCHIVE_WARN);
}
/* End-of-entry cleanup done. */
zip->end_of_entry_cleanup = 1;
}
*offset = zip->entry_uncompressed_bytes_read;
*size = 0;
*buff = NULL;
@ -580,6 +539,44 @@ archive_read_format_zip_read_data(struct archive_read *a,
if (*size)
zip->entry_crc32 =
crc32(zip->entry_crc32, *buff, *size);
/* If we hit the end, swallow any end-of-data marker. */
if (zip->end_of_entry) {
if (zip->flags & ZIP_LENGTH_AT_END) {
const char *p;
if ((p = __archive_read_ahead(a, 16, NULL)) == NULL) {
archive_set_error(&a->archive,
ARCHIVE_ERRNO_FILE_FORMAT,
"Truncated ZIP end-of-file record");
return (ARCHIVE_FATAL);
}
zip->crc32 = archive_le32dec(p + 4);
zip->compressed_size = archive_le32dec(p + 8);
zip->uncompressed_size = archive_le32dec(p + 12);
__archive_read_consume(a, 16);
}
/* Check file size, CRC against these values. */
if (zip->compressed_size != zip->entry_compressed_bytes_read) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"ZIP compressed data is wrong size");
return (ARCHIVE_WARN);
}
/* Size field only stores the lower 32 bits of the actual size. */
if ((zip->uncompressed_size & UINT32_MAX)
!= (zip->entry_uncompressed_bytes_read & UINT32_MAX)) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"ZIP uncompressed data is wrong size");
return (ARCHIVE_WARN);
}
/* Check computed CRC against header */
if (zip->crc32 != zip->entry_crc32) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"ZIP bad CRC: 0x%lx should be 0x%lx",
zip->entry_crc32, zip->crc32);
return (ARCHIVE_WARN);
}
}
/* Return EOF immediately if this is a non-regular file. */
if (AE_IFREG != (zip->mode & AE_IFMT))
return (ARCHIVE_EOF);
@ -761,7 +758,7 @@ archive_read_format_zip_read_data_skip(struct archive_read *a)
zip = (struct zip *)(a->format->data);
/* If we've already read to end of data, we're done. */
if (zip->end_of_entry_cleanup)
if (zip->end_of_entry)
return (ARCHIVE_OK);
/*
@ -788,7 +785,7 @@ archive_read_format_zip_read_data_skip(struct archive_read *a)
return (ARCHIVE_FATAL);
/* This entry is finished and done. */
zip->end_of_entry_cleanup = zip->end_of_entry = 1;
zip->end_of_entry = 1;
return (ARCHIVE_OK);
}

View File

@ -519,6 +519,9 @@ write_data_block(struct archive_write_disk *a, const char *buff, size_t size)
ssize_t bytes_written = 0;
ssize_t block_size = 0, bytes_to_write;
if (size == 0)
return (ARCHIVE_OK);
if (a->filesize == 0 || a->fd < 0) {
archive_set_error(&a->archive, 0,
"Attempt to write to an empty file");