zlib: don't assert on malformed dictionary
authorBen Noordhuis <info@bnoordhuis.nl>
Tue, 22 Jan 2013 12:23:46 +0000 (13:23 +0100)
committerBen Noordhuis <info@bnoordhuis.nl>
Tue, 22 Jan 2013 12:34:43 +0000 (13:34 +0100)
Handle Z_DATA_ERROR errors from inflateSetDictionary() gracefully.
Fixes the following assertion:

  node: ../src/node_zlib.cc:167: static void node::ZCtx::Process
  (uv_work_t*): Assertion `ctx->err_ == 0 && "Failed to set
  dictionary"' failed.
  Aborted (core dumped)

Fixes #4632.

src/node_zlib.cc
test/simple/test-zlib-dictionary-fail.js

index 3674919..deacb71 100644 (file)
@@ -163,12 +163,16 @@ class ZCtx : public ObjectWrap {
           ctx->err_ = inflateSetDictionary(&ctx->strm_,
                                            ctx->dictionary_,
                                            ctx->dictionary_len_);
-          // TODO Handle Z_DATA_ERROR, wrong dictionary
-          assert(ctx->err_ == Z_OK && "Failed to set dictionary");
           if (ctx->err_ == Z_OK) {
 
             // And try to decode again
             ctx->err_ = inflate(&ctx->strm_, ctx->flush_);
+          } else if (ctx->err_ == Z_DATA_ERROR) {
+
+            // Both inflateSetDictionary() and inflate() return Z_DATA_ERROR.
+            // Make it possible for After() to tell a bad dictionary from bad
+            // input.
+            ctx->err_ = Z_NEED_DICT;
           }
         }
         break;
@@ -196,7 +200,11 @@ class ZCtx : public ObjectWrap {
         // normal statuses, not fatal
         break;
       case Z_NEED_DICT:
-        ZCtx::Error(ctx, "Missing dictionary");
+        if (ctx->dictionary_ == NULL) {
+          ZCtx::Error(ctx, "Missing dictionary");
+        } else {
+          ZCtx::Error(ctx, "Bad dictionary");
+        }
         return;
       default:
         // something else.
index f6d1869..fd35a01 100644 (file)
@@ -34,3 +34,15 @@ var zlib = require('zlib');
   // String "test" encoded with dictionary "dict".
   stream.write(Buffer([0x78,0xBB,0x04,0x09,0x01,0xA5]));
 })();
+
+// Should raise an error, not trigger an assertion in src/node_zlib.cc
+(function() {
+  var stream = zlib.createInflate({ dictionary: Buffer('fail') });
+
+  stream.on('error', common.mustCall(function(err) {
+    assert(/Bad dictionary/.test(err.message));
+  }));
+
+  // String "test" encoded with dictionary "dict".
+  stream.write(Buffer([0x78,0xBB,0x04,0x09,0x01,0xA5]));
+})();