Revamp of the Halibut error handling mechanism.
[sgt/halibut] / deflate.c
index 8749397..6bbceae 100644 (file)
--- a/deflate.c
+++ b/deflate.c
@@ -95,7 +95,7 @@
 #define debug_int(x...) ( fprintf(stderr, x) )
 #define debug(x) ( debug_int x )
 #else
-#define debug(x)
+#define debug(x) ((void)0)
 #endif
 
 #ifdef STANDALONE
@@ -1576,11 +1576,11 @@ deflate_compress_ctx *deflate_compress_new(int type)
     {
        int i;
 
-       for (i = 0; i < lenof(out->static_len1); i++)
+       for (i = 0; i < (int)lenof(out->static_len1); i++)
            out->static_len1[i] = (i < 144 ? 8 :
                                   i < 256 ? 9 :
                                   i < 280 ? 7 : 8);
-       for (i = 0; i < lenof(out->static_len2); i++)
+       for (i = 0; i < (int)lenof(out->static_len2); i++)
            out->static_len2[i] = 5;
     }
     hufcodes(out->static_len1, out->static_code1, lenof(out->static_code1));
@@ -2041,7 +2041,8 @@ int deflate_decompress_data(deflate_decompress_ctx *dctx,
 {
     const coderecord *rec;
     const unsigned char *block = (const unsigned char *)vblock;
-    int code, bfinal, btype, rep, dist, nlen, header, cksum;
+    int code, bfinal, btype, rep, dist, nlen, header;
+    unsigned long cksum;
     int error = 0;
 
     if (len == 0) {
@@ -2296,14 +2297,25 @@ int deflate_decompress_data(deflate_decompress_ctx *dctx,
                                             &error);
                if (!dctx->currlentable)
                    goto finished;     /* error code set up by mktable */
-               dctx->currdisttable = mktable(dctx->lengths + dctx->hlit,
-                                             dctx->hdist,
+                if (dctx->hdist == 1 && dctx->lengths[dctx->hlit] == 0) {
+                    /*
+                     * Special case: if the code length list for the
+                     * backward-distance table contains a single zero
+                     * entry, it means this block will never encode a
+                     * backward distance at all (i.e. it's all
+                     * literals).
+                     */
+                    dctx->currdisttable = NULL;
+                } else {
+                    dctx->currdisttable = mktable(dctx->lengths + dctx->hlit,
+                                                  dctx->hdist,
 #ifdef ANALYSIS
-                                             "distance",
+                                                  "distance",
 #endif
-                                             &error);
-               if (!dctx->currdisttable)
-                   goto finished;     /* error code set up by mktable */
+                                                  &error);
+                    if (!dctx->currdisttable)
+                        goto finished;     /* error code set up by mktable */
+                }
                freetable(&dctx->lenlentable);
                dctx->lenlentable = NULL;
                dctx->state = INBLK;
@@ -2373,7 +2385,8 @@ int deflate_decompress_data(deflate_decompress_ctx *dctx,
                    freetable(&dctx->currlentable);
                    dctx->currlentable = NULL;
                }
-               if (dctx->currdisttable != dctx->staticdisttable) {
+               if (dctx->currdisttable &&
+                    dctx->currdisttable != dctx->staticdisttable) {
                    freetable(&dctx->currdisttable);
                    dctx->currdisttable = NULL;
                }
@@ -2395,6 +2408,10 @@ int deflate_decompress_data(deflate_decompress_ctx *dctx,
            dctx->state = GOTLEN;
            break;
          case GOTLEN:
+            if (!dctx->currdisttable) {
+               error = DEFLATE_ERR_NODISTTABLE;
+                goto finished;
+            }
            code = huflookup(&dctx->bits, &dctx->nbits, dctx->currdisttable);
            debug(("recv: dist %d\n", code));
            if (code == -1)
@@ -2442,9 +2459,16 @@ int deflate_decompress_data(deflate_decompress_ctx *dctx,
                goto finished;
            nlen = dctx->bits & 0xFFFF;
            EATBITS(16);
-           if (dctx->uncomplen == 0)
-               dctx->state = OUTSIDEBLK;       /* block is empty */
-           else
+           if (dctx->uncomplen != (nlen ^ 0xFFFF)) {
+                error = DEFLATE_ERR_UNCOMP_HDR;
+                goto finished;
+            }
+           if (dctx->uncomplen == 0) {/* block is empty */
+               if (dctx->lastblock)
+                   dctx->state = END;
+               else
+                   dctx->state = OUTSIDEBLK;
+           } else
                dctx->state = UNCOMP_DATA;
            break;
          case UNCOMP_DATA:
@@ -2457,8 +2481,12 @@ int deflate_decompress_data(deflate_decompress_ctx *dctx,
 #endif
            emit_char(dctx, dctx->bits & 0xFF);
            EATBITS(8);
-           if (--dctx->uncomplen == 0)
-               dctx->state = OUTSIDEBLK;       /* end of uncompressed block */
+           if (--dctx->uncomplen == 0) {       /* end of uncompressed block */
+               if (dctx->lastblock)
+                   dctx->state = END;
+               else
+                   dctx->state = OUTSIDEBLK;
+           }
            break;
          case END:
            /*
@@ -2573,6 +2601,15 @@ const char *const deflate_error_sym[DEFLATE_NUM_ERRORS] = {
 };
 #undef A
 
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64)
+#define WINDOWS_IO
+#endif
+
+#if defined(WINDOWS_IO) && (defined(STANDALONE) || defined(TESTMODE))
+#include <fcntl.h>
+#include <io.h>
+#endif
+
 #ifdef STANDALONE
 
 int main(int argc, char **argv)
@@ -2648,6 +2685,14 @@ int main(int argc, char **argv)
         fprintf(stderr, "unable to open '%s'\n", filename);
         return 1;
     }
+    
+#ifdef WINDOWS_IO   
+    if(_setmode(_fileno(stdout), _O_BINARY ) == -1)
+    {
+        fprintf(stderr, "Can't set stdout to binary mode\n");
+        return 1;
+    }
+#endif
 
     do {
        ret = fread(buf, 1, sizeof(buf), fp);
@@ -2736,6 +2781,14 @@ int main(int argc, char **argv)
 
     chandle = deflate_compress_new(DEFLATE_TYPE_ZLIB);
     dhandle = deflate_decompress_new(DEFLATE_TYPE_ZLIB);
+    
+#ifdef WINDOWS_IO   
+    if(_setmode(_fileno(stdout), _O_BINARY ) == -1)
+    {
+        fprintf(stderr, "Can't set stdout to binary mode\n");
+        return 1;
+    }
+#endif
 
     do {
        ret = fread(buf, 1, sizeof(buf), fp);