Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

zlib: fix error reporting

This commit is a back-port of the changes on the master branch.

Fixes #3230.
  • Loading branch information...
bnoordhuis committed May 7, 2012
1 parent 8c758e1 commit ee437c0557c9f3a6a1960d3a8d64e09166d7048d
Showing with 297 additions and 69 deletions.
  1. +60 −10 lib/zlib.js
  2. +200 −57 src/node_zlib.cc
  3. +36 −2 test/simple/test-zlib-invalid-input.js
  4. +1 −0 test/simple/test-zlib-random-byte-pipes.js
@@ -50,6 +50,22 @@ Object.keys(binding).forEach(function(k) {
if (k.match(/^Z/)) exports[k] = binding[k];
});

// translation table for return codes.
exports.codes = {
Z_OK: binding.Z_OK,
Z_STREAM_END: binding.Z_STREAM_END,
Z_NEED_DICT: binding.Z_NEED_DICT,
Z_ERRNO: binding.Z_ERRNO,
Z_STREAM_ERROR: binding.Z_STREAM_ERROR,
Z_DATA_ERROR: binding.Z_DATA_ERROR,
Z_MEM_ERROR: binding.Z_MEM_ERROR,
Z_BUF_ERROR: binding.Z_BUF_ERROR,
Z_VERSION_ERROR: binding.Z_VERSION_ERROR
};

Object.keys(exports.codes).forEach(function(k) {
exports.codes[exports.codes[k]] = k;
});

exports.Deflate = Deflate;
exports.Inflate = Inflate;
@@ -135,7 +151,7 @@ function zlibBuffer(engine, buffer, callback) {

function onEnd() {
var buffer;
switch(buffers.length) {
switch (buffers.length) {
case 0:
buffer = new Buffer(0);
break;
@@ -169,45 +185,45 @@ function zlibBuffer(engine, buffer, callback) {
// minimal 2-byte header
function Deflate(opts) {
if (!(this instanceof Deflate)) return new Deflate(opts);
Zlib.call(this, opts, binding.Deflate);
Zlib.call(this, opts, binding.DEFLATE);
}

function Inflate(opts) {
if (!(this instanceof Inflate)) return new Inflate(opts);
Zlib.call(this, opts, binding.Inflate);
Zlib.call(this, opts, binding.INFLATE);
}



// gzip - bigger header, same deflate compression
function Gzip(opts) {
if (!(this instanceof Gzip)) return new Gzip(opts);
Zlib.call(this, opts, binding.Gzip);
Zlib.call(this, opts, binding.GZIP);
}

function Gunzip(opts) {
if (!(this instanceof Gunzip)) return new Gunzip(opts);
Zlib.call(this, opts, binding.Gunzip);
Zlib.call(this, opts, binding.GUNZIP);
}



// raw - no header
function DeflateRaw(opts) {
if (!(this instanceof DeflateRaw)) return new DeflateRaw(opts);
Zlib.call(this, opts, binding.DeflateRaw);
Zlib.call(this, opts, binding.DEFLATERAW);
}

function InflateRaw(opts) {
if (!(this instanceof InflateRaw)) return new InflateRaw(opts);
Zlib.call(this, opts, binding.InflateRaw);
Zlib.call(this, opts, binding.INFLATERAW);
}


// auto-detect header.
function Unzip(opts) {
if (!(this instanceof Unzip)) return new Unzip(opts);
Zlib.call(this, opts, binding.Unzip);
Zlib.call(this, opts, binding.UNZIP);
}


@@ -216,7 +232,7 @@ function Unzip(opts) {
// true or false if there is anything in the queue when
// you call the .write() method.

function Zlib(opts, Binding) {
function Zlib(opts, mode) {
this._opts = opts = opts || {};
this._queue = [];
this._processing = false;
@@ -263,7 +279,23 @@ function Zlib(opts, Binding) {
}
}

this._binding = new Binding();
this._binding = new binding.Zlib(mode);

var self = this;
this._binding.onerror = function(message, errno) {
// there is no way to cleanly recover.
// continuing only obscures problems.
self._binding = null;
self._hadError = true;
self._queue.length = 0;
self._processing = false;

var error = new Error(message);
error.errno = errno;
error.code = exports.codes[errno];
self.emit('error', error);
};

this._binding.init(opts.windowBits || exports.Z_DEFAULT_WINDOWBITS,
opts.level || exports.Z_DEFAULT_COMPRESSION,
opts.memLevel || exports.Z_DEFAULT_MEMLEVEL,
@@ -278,6 +310,8 @@ function Zlib(opts, Binding) {
util.inherits(Zlib, stream.Stream);

Zlib.prototype.write = function write(chunk, cb) {
if (this._hadError) return true;

if (this._ended) {
return this.emit('error', new Error('Cannot write after end'));
}
@@ -306,12 +340,18 @@ Zlib.prototype.write = function write(chunk, cb) {
return empty;
};

Zlib.prototype.reset = function reset() {
return this._binding.reset();
};

Zlib.prototype.flush = function flush(cb) {
this._flush = binding.Z_SYNC_FLUSH;
return this.write(cb);
};

Zlib.prototype.end = function end(chunk, cb) {
if (this._hadError) return true;

var self = this;
this._ending = true;
var ret = this.write(chunk, function() {
@@ -323,6 +363,8 @@ Zlib.prototype.end = function end(chunk, cb) {
};

Zlib.prototype._process = function() {
if (this._hadError) return;

if (this._processing || this._paused) return;

if (this._queue.length === 0) {
@@ -360,6 +402,8 @@ Zlib.prototype._process = function() {
this._processing = req;

function callback(availInAfter, availOutAfter, buffer) {
if (self._hadError) return;

var have = availOutBefore - availOutAfter;

assert(have >= 0, 'have should not go down');
@@ -416,6 +460,12 @@ Zlib.prototype.resume = function() {
this._process();
};

Zlib.prototype.destroy = function() {
this.readable = false;
this.writable = false;
this._ended = true;
};

util.inherits(Deflate, Zlib);
util.inherits(Inflate, Zlib);
util.inherits(Gzip, Zlib);

0 comments on commit ee437c0

Please sign in to comment.
You can’t perform that action at this time.