]> granicus.if.org Git - php/commitdiff
- fixed bug #49072, feof never returns true for damaged file in zip
authorPierre Joye <pajoye@php.net>
Tue, 11 Aug 2009 15:12:00 +0000 (15:12 +0000)
committerPierre Joye <pajoye@php.net>
Tue, 11 Aug 2009 15:12:00 +0000 (15:12 +0000)
NEWS
ext/zip/lib/zip_fread.c
ext/zip/tests/bug49072.phpt [new file with mode: 0644]
ext/zip/tests/bug49072.zip [new file with mode: 0644]
ext/zip/zip_stream.c

diff --git a/NEWS b/NEWS
index 8d6a0fc65a8e57b908202bfb27d9babf72e0cc5a..161ca05c152e0d0891ce64ae89dfb8e9675c3397 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,7 @@ PHP                                                                        NEWS
 - Fixed bug #49095 (proc_get_status['exitcode'] fails on win32). (Felipe)
 - Fixed bug #49074 (private class static fields can be modified by using
   reflection). (Jani)
+- Fixed bug #49072 (feof never returns true for damaged file in zip). (Pierre)
 - Fixed bug #49052 (context option headers freed too early when using
   --with-curlwrappers). (Jani)
 - Fixed bug #49032 (SplFileObject::fscanf() variables passed by reference).
index 1a2b0e3816e4d4f8b8f313463c11d3fa45d323dd..861c865c8a553beff577200300b2c89183047660 100644 (file)
@@ -83,15 +83,26 @@ zip_fread(struct zip_file *zf, void *outbuf, size_t toread)
        ret = inflate(zf->zstr, Z_SYNC_FLUSH);
 
        switch (ret) {
-       case Z_OK:
        case Z_STREAM_END:
+               zf->flags |= ZIP_ZF_EOF;
+
+       case Z_OK:
+
            /* all ok */
            /* Z_STREAM_END probably won't happen, since we didn't
               have a header */
            len = zf->zstr->total_out - out_before;
            if (len >= zf->bytes_left || len >= toread) {
-               if (zf->flags & ZIP_ZF_CRC)
-                   zf->crc = crc32(zf->crc, (Bytef *)outbuf, len);
+                   if (zf->flags & ZIP_ZF_CRC) {
+                           zf->crc = crc32(zf->crc, (Bytef *)outbuf, len);
+                           if (zf->flags & ZIP_ZF_EOF == 1) {
+                                   if (zf->crc != zf->crc_orig) {
+                                           _zip_error_set(&zf->error, ZIP_ER_CRC, 0);
+                                           return -1;
+                                   }
+
+                           }
+                   }
                zf->bytes_left -= len;
                return len;
            }
diff --git a/ext/zip/tests/bug49072.phpt b/ext/zip/tests/bug49072.phpt
new file mode 100644 (file)
index 0000000..04bd06e
--- /dev/null
@@ -0,0 +1,24 @@
+--TEST--
+Bug #49072 (feof never returns true for damaged file in zip)
+--SKIPIF--
+<?php
+/* $Id$ */
+if(!extension_loaded('zip')) die('skip');
+?>
+--FILE--
+<?php
+$f = dirname(__FILE__)  . '/bug49072.zip';
+$o = new ZipArchive();
+if (! $o->open($f, ZipArchive::CHECKCONS)) {
+       exit ('error can\'t open');
+}
+$r = $o->getStream('file1'); // this file has a wrong crc
+if (!$r)die('failed to open a stream for file1');
+$s = '';
+while (! feof($r)) {
+       $s .= fread($r,1024);
+}
+?>
+--EXPECTF--
+
+Warning: fread(): Zip stream error: CRC error in %s on line %d
diff --git a/ext/zip/tests/bug49072.zip b/ext/zip/tests/bug49072.zip
new file mode 100644 (file)
index 0000000..16bbcd0
Binary files /dev/null and b/ext/zip/tests/bug49072.zip differ
index 1f305509ea26bf54c50540f17da6cf3cad743c74..202e2a44f519ddb7e9b0bfda39dfd452e0e7c57b 100644 (file)
@@ -35,8 +35,14 @@ static size_t php_zip_ops_read(php_stream *stream, char *buf, size_t count TSRML
 
        if (self->za && self->zf) {
                n = (size_t)zip_fread(self->zf, buf, (int)count);
-
-               if (n == 0) {
+               if (n < 0) {
+                       int ze, se;
+                       zip_file_error_get(self->zf, &ze, &se);
+                       stream->eof = 1;
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zip stream error: %s", zip_file_strerror(self->zf));
+                       return 0;
+               }
+               if (n == 0 || n < count) {
                        stream->eof = 1;
                } else {
                        self->cursor += n;