mirror of https://github.com/nodejs/node.git
zlib: fix assert on bad input
The following test case occasionally triggered an assert because write_in_progress_ didn't get cleared on error: $ cat test.js require('zlib').gunzip('BAM', console.log); setTimeout(gc, 10); $ while true; do node --expose-gc test.js || break; done { [Error: incorrect header check] errno: -3, code: 'Z_DATA_ERROR' } Assertion failed: (!write_in_progress_ && "write in progress"), function Clear, file ../src/node_zlib.cc, line 71. Abort trap: 6 Steps to avoid that: * Initialize all primitive member fields in the constructor. * Clear the write_in_progress_ member field in ZCtx::Error(). * Ref the ZCtx object as soon as write_in_progress_ is set to true. Before this commit, it could get GC'ed in the time between setting the field and the call to ctx->Ref(). Fixes #4783.pull/24501/head
parent
9d45b945f7
commit
ef94521909
|
@ -59,7 +59,22 @@ void InitZlib(v8::Handle<v8::Object> target);
|
||||||
class ZCtx : public ObjectWrap {
|
class ZCtx : public ObjectWrap {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ZCtx(node_zlib_mode mode) : ObjectWrap(), dictionary_(NULL), mode_(mode) {}
|
ZCtx(node_zlib_mode mode)
|
||||||
|
: ObjectWrap()
|
||||||
|
, init_done_(false)
|
||||||
|
, level_(0)
|
||||||
|
, windowBits_(0)
|
||||||
|
, memLevel_(0)
|
||||||
|
, strategy_(0)
|
||||||
|
, err_(0)
|
||||||
|
, dictionary_(NULL)
|
||||||
|
, dictionary_len_(0)
|
||||||
|
, flush_(0)
|
||||||
|
, chunk_size_(0)
|
||||||
|
, write_in_progress_(false)
|
||||||
|
, mode_(mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
~ZCtx() {
|
~ZCtx() {
|
||||||
|
@ -108,6 +123,7 @@ class ZCtx : public ObjectWrap {
|
||||||
|
|
||||||
assert(!ctx->write_in_progress_ && "write already in progress");
|
assert(!ctx->write_in_progress_ && "write already in progress");
|
||||||
ctx->write_in_progress_ = true;
|
ctx->write_in_progress_ = true;
|
||||||
|
ctx->Ref();
|
||||||
|
|
||||||
unsigned int flush = args[0]->Uint32Value();
|
unsigned int flush = args[0]->Uint32Value();
|
||||||
Bytef *in;
|
Bytef *in;
|
||||||
|
@ -155,8 +171,6 @@ class ZCtx : public ObjectWrap {
|
||||||
ZCtx::Process,
|
ZCtx::Process,
|
||||||
ZCtx::After);
|
ZCtx::After);
|
||||||
|
|
||||||
ctx->Ref();
|
|
||||||
|
|
||||||
return ctx->handle_;
|
return ctx->handle_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,6 +283,7 @@ class ZCtx : public ObjectWrap {
|
||||||
MakeCallback(ctx->handle_, onerror_sym, ARRAY_SIZE(args), args);
|
MakeCallback(ctx->handle_, onerror_sym, ARRAY_SIZE(args), args);
|
||||||
|
|
||||||
// no hope of rescue.
|
// no hope of rescue.
|
||||||
|
ctx->write_in_progress_ = false;
|
||||||
ctx->Unref();
|
ctx->Unref();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue