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 {
|
||||
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() {
|
||||
|
@ -108,6 +123,7 @@ class ZCtx : public ObjectWrap {
|
|||
|
||||
assert(!ctx->write_in_progress_ && "write already in progress");
|
||||
ctx->write_in_progress_ = true;
|
||||
ctx->Ref();
|
||||
|
||||
unsigned int flush = args[0]->Uint32Value();
|
||||
Bytef *in;
|
||||
|
@ -155,8 +171,6 @@ class ZCtx : public ObjectWrap {
|
|||
ZCtx::Process,
|
||||
ZCtx::After);
|
||||
|
||||
ctx->Ref();
|
||||
|
||||
return ctx->handle_;
|
||||
}
|
||||
|
||||
|
@ -269,6 +283,7 @@ class ZCtx : public ObjectWrap {
|
|||
MakeCallback(ctx->handle_, onerror_sym, ARRAY_SIZE(args), args);
|
||||
|
||||
// no hope of rescue.
|
||||
ctx->write_in_progress_ = false;
|
||||
ctx->Unref();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue