Skip to content
This repository was archived by the owner on Apr 22, 2023. It is now read-only.

Commit 829a9b8

Browse files
committed
zlib: introduce pending close state
zlib should not crash in `close()` if the write is still in progress. fix #7101
1 parent 86b8d84 commit 829a9b8

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

src/node_zlib.cc

+14-1
Original file line numberDiff line numberDiff line change
@@ -72,18 +72,25 @@ class ZCtx : public ObjectWrap {
7272
, flush_(0)
7373
, chunk_size_(0)
7474
, write_in_progress_(false)
75+
, pending_close_(false)
7576
, mode_(mode)
7677
{
7778
}
7879

7980

8081
~ZCtx() {
82+
assert(!write_in_progress_ && "write in progress");
8183
Close();
8284
}
8385

8486

8587
void Close() {
86-
assert(!write_in_progress_ && "write in progress");
88+
if (write_in_progress_) {
89+
pending_close_ = true;
90+
return;
91+
}
92+
93+
pending_close_ = false;
8794
assert(init_done_ && "close before init");
8895
assert(mode_ <= UNZIP);
8996

@@ -122,6 +129,7 @@ class ZCtx : public ObjectWrap {
122129
assert(ctx->mode_ != NONE && "already finalized");
123130

124131
assert(!ctx->write_in_progress_ && "write already in progress");
132+
assert(!ctx->pending_close_ && "close is pending");
125133
ctx->write_in_progress_ = true;
126134
ctx->Ref();
127135

@@ -279,6 +287,8 @@ class ZCtx : public ObjectWrap {
279287
MakeCallback(ctx->handle_, callback_sym, ARRAY_SIZE(args), args);
280288

281289
ctx->Unref();
290+
if (ctx->pending_close_)
291+
ctx->Close();
282292
}
283293

284294
static void Error(ZCtx *ctx, const char *msg_) {
@@ -299,6 +309,8 @@ class ZCtx : public ObjectWrap {
299309
// no hope of rescue.
300310
ctx->write_in_progress_ = false;
301311
ctx->Unref();
312+
if (ctx->pending_close_)
313+
ctx->Close();
302314
}
303315

304316
static Handle<Value> New(const Arguments& args) {
@@ -495,6 +507,7 @@ class ZCtx : public ObjectWrap {
495507
int chunk_size_;
496508

497509
bool write_in_progress_;
510+
bool pending_close_;
498511

499512
uv_work_t work_req_;
500513
node_zlib_mode mode_;
+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright Joyent, Inc. and other Node contributors.
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a
4+
// copy of this software and associated documentation files (the
5+
// "Software"), to deal in the Software without restriction, including
6+
// without limitation the rights to use, copy, modify, merge, publish,
7+
// distribute, sublicense, and/or sell copies of the Software, and to permit
8+
// persons to whom the Software is furnished to do so, subject to the
9+
// following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included
12+
// in all copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17+
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18+
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20+
// USE OR OTHER DEALINGS IN THE SOFTWARE.
21+
22+
var common = require('../common.js');
23+
var assert = require('assert');
24+
var zlib = require('zlib');
25+
26+
var closed = false;
27+
28+
zlib.gzip('hello', function(err, out) {
29+
var unzip = zlib.createGunzip();
30+
unzip.write(out);
31+
unzip.close(function() {
32+
closed = true;
33+
});
34+
});
35+
36+
process.on('exit', function() {
37+
assert(closed);
38+
});

0 commit comments

Comments
 (0)