]> granicus.if.org Git - php/commitdiff
fix PHP bug #48791: open office files always reported as corrupted
authorGreg Beaver <cellog@php.net>
Thu, 23 Jul 2009 16:30:27 +0000 (16:30 +0000)
committerGreg Beaver <cellog@php.net>
Thu, 23 Jul 2009 16:30:27 +0000 (16:30 +0000)
NEWS
ext/phar/phar.c
ext/phar/pharzip.h

diff --git a/NEWS b/NEWS
index c1ea6fd4e596bad52eb13a281f66235ceacf520c..56018f9bdec38d970b3f090ad74a0a48c3c32b88 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,7 @@ PHP                                                                        NEWS
 - Fixed bug #48854 (array_merge_recursive modifies arrays after first one).
   (Felipe)
 - Fixed bug #48802 (printf() returns incorrect outputted length). (Jani)
+- Fixed bug #48791 (open office files always reported as corrupted). (Greg)
 - Fixed bug #48788 (RecursiveDirectoryIterator doesn't descend into symlinked
   directories). (Ilia)
 - Fixed bug #48783 (make install will fail saying phar file exists). (Greg)
index 29642067a0fd1e5c13081c32769e3faf5dbe558b..ec441ee04a867cd5d7d8bd8e5404771566286bf2 100644 (file)
@@ -2407,6 +2407,7 @@ int phar_postprocess_file(phar_entry_data *idata, php_uint32 crc32, char **error
        if (entry->is_zip && process_zip > 0) {
                /* verify local file header */
                phar_zip_file_header local;
+               phar_zip_data_desc desc;
 
                if (SUCCESS != phar_open_archive_fp(idata->phar TSRMLS_CC)) {
                        spprintf(error, 0, "phar error: unable to open zip-based phar archive \"%s\" to verify local file header for file \"%s\"", idata->phar->fname, entry->filename);
@@ -2420,6 +2421,25 @@ int phar_postprocess_file(phar_entry_data *idata, php_uint32 crc32, char **error
                        return FAILURE;
                }
 
+               /* check for data descriptor */
+               if (((PHAR_ZIP_16(local.flags)) & 0x8) == 0x8) {
+                       php_stream_seek(phar_get_entrypfp(idata->internal_file TSRMLS_CC),
+                                       entry->header_offset + sizeof(local) +
+                                       PHAR_ZIP_16(local.filename_len) +
+                                       PHAR_ZIP_16(local.extra_len) +
+                                       entry->compressed_filesize, SEEK_SET);
+                       if (sizeof(desc) != php_stream_read(phar_get_entrypfp(idata->internal_file TSRMLS_CC),
+                                                           (char *) &desc, sizeof(desc))) {
+                               spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (cannot read local data descriptor for file \"%s\")", idata->phar->fname, entry->filename);
+                               return FAILURE;
+                       }
+                       if (desc.signature[0] == 'P' && desc.signature[1] == 'K') {
+                               memcpy(&(local.crc32), &(desc.crc32), 12);
+                       } else {
+                               /* old data descriptors have no signature */
+                               memcpy(&(local.crc32), &desc, 12);
+                       }
+               }
                /* verify local header */
                if (entry->filename_len != PHAR_ZIP_16(local.filename_len) || entry->crc32 != PHAR_ZIP_32(local.crc32) || entry->uncompressed_filesize != PHAR_ZIP_32(local.uncompsize) || entry->compressed_filesize != PHAR_ZIP_32(local.compsize)) {
                        spprintf(error, 0, "phar error: internal corruption of zip-based phar \"%s\" (local header of file \"%s\" does not match central directory)", idata->phar->fname, entry->filename);
index 47307d49c3be2a3f82205d953654edd8b528a5cb..590821f8cb3f4a9fc36dd8a52708c3ef13c1dd05 100644 (file)
@@ -37,6 +37,7 @@ typedef struct _phar_zip_file_header {
 
 /* unused in this release */
 typedef struct _phar_zip_file_datadesc {
+       char signature[4];  /* signature (optional)            4 bytes */
        char crc32[4];      /* crc-32                          4 bytes */
        char compsize[4];   /* compressed size                 4 bytes */
        char uncompsize[4]; /* uncompressed size               4 bytes */