From owner-svn-src-all@FreeBSD.ORG Fri Mar 6 04:50:39 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C0FDB1065670; Fri, 6 Mar 2009 04:50:39 +0000 (UTC) (envelope-from kientzle@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id AE6E28FC0C; Fri, 6 Mar 2009 04:50:39 +0000 (UTC) (envelope-from kientzle@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n264od3G008382; Fri, 6 Mar 2009 04:50:39 GMT (envelope-from kientzle@svn.freebsd.org) Received: (from kientzle@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n264odVW008380; Fri, 6 Mar 2009 04:50:39 GMT (envelope-from kientzle@svn.freebsd.org) Message-Id: <200903060450.n264odVW008380@svn.freebsd.org> From: Tim Kientzle Date: Fri, 6 Mar 2009 04:50:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r189430 - head/lib/libarchive X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 06 Mar 2009 04:50:40 -0000 Author: kientzle Date: Fri Mar 6 04:50:39 2009 New Revision: 189430 URL: http://svn.freebsd.org/changeset/base/189430 Log: 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. Modified: head/lib/libarchive/archive_read_support_format_zip.c head/lib/libarchive/archive_write_disk.c Modified: head/lib/libarchive/archive_read_support_format_zip.c ============================================================================== --- head/lib/libarchive/archive_read_support_format_zip.c Fri Mar 6 04:35:31 2009 (r189429) +++ head/lib/libarchive/archive_read_support_format_zip.c Fri Mar 6 04:50:39 2009 (r189430) @@ -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(stru 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(stru 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_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 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(s 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(s 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); } Modified: head/lib/libarchive/archive_write_disk.c ============================================================================== --- head/lib/libarchive/archive_write_disk.c Fri Mar 6 04:35:31 2009 (r189429) +++ head/lib/libarchive/archive_write_disk.c Fri Mar 6 04:50:39 2009 (r189430) @@ -519,6 +519,9 @@ write_data_block(struct archive_write_di 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");