libzip: libzip-discuss: fix fread with invalid crc or broken archive (0.9)

Thread

Thread Index

Message

From: Pierre Joye <pierre.php%gmail.com@localhost>
To: libzip-discuss%nih.at@localhost
Subject: fix fread with invalid crc or broken archive (0.9)
Date: Thu, 6 Aug 2009 13:22:03 +0200

hi,

Please find a patch as attachment to fix http://bugs.php.net/49072.
This patch may be useful for the current users to avoid DoS or random
crashes (infinite loop). It passes all the php zip extension tests. I
would like to apply it to our bundled library in php 5.2/5.3 (php6
will certainly have the newest version). Please let me know if you
find any issue with it.

The bug appears only in the current release. The development tree
works correctly and a bad CRC error is raised.

A test archive can be found here: pierre.libgd.org/zip/49072.zip

Cheers,
-- 
Pierre

http://blog.thepimp.net | http://www.libgd.org
Index: zip_fread.c
===================================================================
--- zip_fread.c (revision 286850)
+++ zip_fread.c (working copy)
@@ -63,7 +63,7 @@
        }
        return 0;
     }
-    
+ 
     if ((zf->flags & ZIP_ZF_DECOMP) == 0) {
        ret = _zip_file_fillbuf(outbuf, toread, zf);
        if (ret > 0) {
@@ -83,15 +83,26 @@
        ret = inflate(zf->zstr, Z_SYNC_FLUSH);
 
        switch (ret) {
+       case Z_STREAM_END:
+               zf->flags |= ZIP_ZF_EOF;
+
        case Z_OK:
-       case Z_STREAM_END:
+
            /* 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;
            }

Made by MHonArc.