]> 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 26c60ced838bf153188b3556f35da34cbd2f15a2..1f37939e373aaca1d02c97008462519ec03b64e8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -24,6 +24,7 @@ PHP                                                                        NEWS
   qualified namespaces). (Kalle, Jani)
 - 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 #49108 (2nd scan_dir produces segfault). (Felipe)
 - Fixed bug #49065 ("disable_functions" php.ini option does not work on 
   Zend extensions). (Stas)
index 1a2b0e3816e4d4f8b8f313463c11d3fa45d323dd..c0b71b86195f62d7e48a83a667ad722331e54add 100644 (file)
@@ -63,7 +63,7 @@ zip_fread(struct zip_file *zf, void *outbuf, size_t toread)
        }
        return 0;
     }
-    
     if ((zf->flags & ZIP_ZF_DECOMP) == 0) {
        ret = _zip_file_fillbuf(outbuf, toread, zf);
        if (ret > 0) {
@@ -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..a51290f75ba11a5a43441349e53b7a09ba347d42 100644 (file)
@@ -6,6 +6,7 @@
 #if HAVE_ZIP
 #ifdef ZEND_ENGINE_2
 
+#include "lib/zip.h"
 #include "lib/zip.h"
 
 #include "php_streams.h"
@@ -35,14 +36,20 @@ 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;
                }
        }
-       return n<1 ? 0 : n;
+       return (n < 1 ? 0 : n);
 }
 /* }}} */
 
@@ -62,14 +69,15 @@ static int php_zip_ops_close(php_stream *stream, int close_handle TSRMLS_DC)
 {
        STREAM_DATA_FROM_STREAM();
        if (close_handle) {
-               if (self->za) {
-                       zip_close(self->za);
-                       self->za = NULL;
-               }
                if (self->zf) {
                        zip_fclose(self->zf);
                        self->zf = NULL;
                }
+
+               if (self->za) {
+                       zip_close(self->za);
+                       self->za = NULL;
+               }
        }
        efree(self);
        stream->abstract = NULL;