Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zlib: do not leak on destroy #23734

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions lib/zlib.js
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,11 @@ Zlib.prototype.close = function close(callback) {
this.destroy();
};

Zlib.prototype._destroy = function _destroy(err, callback) {
_close(this);
callback(err);
mcollina marked this conversation as resolved.
Show resolved Hide resolved
};
addaleax marked this conversation as resolved.
Show resolved Hide resolved

Zlib.prototype._transform = function _transform(chunk, encoding, cb) {
var flushFlag = this._defaultFlushFlag;
// We use a 'fake' zero-length chunk to carry information about flushes from
Expand Down Expand Up @@ -592,6 +597,10 @@ function processCallback() {
assert(false, 'have should not go down');
}

if (self.destroyed) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already a check for this a few line above, isn't that one sufficient?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the idea is that the push() call can trigger on('data') listeners which can destroy the stream?

Either way, it would be great to have a test for this (and the other bits in this PR)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, makes sense, I think a comment would also help.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually already tested as the existing tests fail (crash even!) without this.

return;
}

// exhausted the output buffer, or used all the input create a new one.
if (availOutAfter === 0 || self._outOffset >= self._chunkSize) {
handle.availOutBefore = self._chunkSize;
Expand Down
10 changes: 10 additions & 0 deletions test/parallel/test-zlib-close-in-ondata.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use strict';

const common = require('../common');
const zlib = require('zlib');

const ts = zlib.createGzip();
const buf = Buffer.alloc(1024 * 1024 * 20);

ts.on('data', common.mustCall(() => ts.close()));
ts.end(buf);
13 changes: 13 additions & 0 deletions test/parallel/test-zlib-destroy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';

require('../common');

const assert = require('assert');
const zlib = require('zlib');

// verify that the zlib transform does clean up
// the handle when calling destroy.

const ts = zlib.createGzip();
ts.destroy();
assert.strictEqual(ts._handle, null);