summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2013-02-21 23:58:55 +0100
committerBen Noordhuis <info@bnoordhuis.nl>2013-02-22 00:08:26 +0100
commitef945219090de0c04884528f4113435499cc8ec3 (patch)
tree5e01c679206c8f476d7d895edfeb47e300e77969
parent9d45b945f7903ea7db8427fe8b9cf08fd8d42ef5 (diff)
downloadnode-new-ef945219090de0c04884528f4113435499cc8ec3.tar.gz
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.
-rw-r--r--src/node_zlib.cc21
1 files changed, 18 insertions, 3 deletions
diff --git a/src/node_zlib.cc b/src/node_zlib.cc
index 4a60c875d7..7c7f966cd6 100644
--- a/src/node_zlib.cc
+++ b/src/node_zlib.cc
@@ -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();
}