diff options
author | Trevor Norris <trev.norris@gmail.com> | 2016-04-13 13:16:42 -0600 |
---|---|---|
committer | Rod Vagg <rod@vagg.org> | 2016-06-02 22:39:22 +1000 |
commit | 4333fda46d1feaab4afb75f31349f21c0c62fc40 (patch) | |
tree | 7ee66ee20043508961b9132385fe9f8f39d849df | |
parent | 0d08fc415f12a4ea8babfad0d72ccda50a3e2c25 (diff) | |
download | node-new-4333fda46d1feaab4afb75f31349f21c0c62fc40.tar.gz |
src: no abort from getter if object isn't wrapped
v8::Object::GetAlignedPointerFromInternalField() returns a random value
if Wrap() hasn't been run on the object handle. Causing v8 to abort if
certain getters are accessed. It's possible to access these getters and
functions during class construction through the AsyncWrap init()
callback, and also possible in a subset of those scenarios while running
the persistent handle visitor.
Mitigate this issue by manually setting the internal aligned pointer
field to nullptr in the BaseObject constructor and add necessary logic
to return appropriate values when nullptr is encountered.
PR-URL: https://github.com/nodejs/node/pull/6184
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
-rw-r--r-- | src/base-object-inl.h | 4 | ||||
-rw-r--r-- | src/fs_event_wrap.cc | 6 | ||||
-rw-r--r-- | src/handle_wrap.cc | 12 | ||||
-rw-r--r-- | src/js_stream.cc | 23 | ||||
-rw-r--r-- | src/node_contextify.cc | 23 | ||||
-rw-r--r-- | src/node_crypto.cc | 276 | ||||
-rw-r--r-- | src/node_http_parser.cc | 24 | ||||
-rw-r--r-- | src/node_internals.h | 2 | ||||
-rw-r--r-- | src/node_stat_watcher.cc | 6 | ||||
-rw-r--r-- | src/node_wrap.h | 2 | ||||
-rw-r--r-- | src/node_zlib.cc | 15 | ||||
-rw-r--r-- | src/pipe_wrap.cc | 18 | ||||
-rw-r--r-- | src/process_wrap.cc | 7 | ||||
-rw-r--r-- | src/signal_wrap.cc | 6 | ||||
-rw-r--r-- | src/stream_base-inl.h | 16 | ||||
-rw-r--r-- | src/stream_base.cc | 3 | ||||
-rw-r--r-- | src/stream_wrap.cc | 6 | ||||
-rw-r--r-- | src/tcp_wrap.cc | 46 | ||||
-rw-r--r-- | src/tls_wrap.cc | 28 | ||||
-rw-r--r-- | src/tty_wrap.cc | 10 | ||||
-rw-r--r-- | src/udp_wrap.cc | 29 | ||||
-rw-r--r-- | src/util.h | 20 | ||||
-rw-r--r-- | test/parallel/test-stream-base-no-abort.js | 58 |
23 files changed, 462 insertions, 178 deletions
diff --git a/src/base-object-inl.h b/src/base-object-inl.h index 87159ffc68..86add5e3b3 100644 --- a/src/base-object-inl.h +++ b/src/base-object-inl.h @@ -14,6 +14,10 @@ inline BaseObject::BaseObject(Environment* env, v8::Local<v8::Object> handle) : handle_(env->isolate(), handle), env_(env) { CHECK_EQ(false, handle.IsEmpty()); + // The zero field holds a pointer to the handle. Immediately set it to + // nullptr in case it's accessed by the user before construction is complete. + if (handle->InternalFieldCount() > 0) + handle->SetAlignedPointerInInternalField(0, nullptr); } diff --git a/src/fs_event_wrap.cc b/src/fs_event_wrap.cc index 48b6f4eca8..3f0df1140c 100644 --- a/src/fs_event_wrap.cc +++ b/src/fs_event_wrap.cc @@ -86,7 +86,8 @@ void FSEventWrap::New(const FunctionCallbackInfo<Value>& args) { void FSEventWrap::Start(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - FSEventWrap* wrap = Unwrap<FSEventWrap>(args.Holder()); + FSEventWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); static const char kErrMsg[] = "filename must be a string or Buffer"; if (args.Length() < 1) @@ -181,7 +182,8 @@ void FSEventWrap::OnEvent(uv_fs_event_t* handle, const char* filename, void FSEventWrap::Close(const FunctionCallbackInfo<Value>& args) { - FSEventWrap* wrap = Unwrap<FSEventWrap>(args.Holder()); + FSEventWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); if (wrap == nullptr || wrap->initialized_ == false) return; diff --git a/src/handle_wrap.cc b/src/handle_wrap.cc index c5792338af..daf821e1d2 100644 --- a/src/handle_wrap.cc +++ b/src/handle_wrap.cc @@ -18,7 +18,8 @@ using v8::Value; void HandleWrap::Ref(const FunctionCallbackInfo<Value>& args) { - HandleWrap* wrap = Unwrap<HandleWrap>(args.Holder()); + HandleWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); if (IsAlive(wrap)) uv_ref(wrap->GetHandle()); @@ -26,7 +27,8 @@ void HandleWrap::Ref(const FunctionCallbackInfo<Value>& args) { void HandleWrap::Unref(const FunctionCallbackInfo<Value>& args) { - HandleWrap* wrap = Unwrap<HandleWrap>(args.Holder()); + HandleWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); if (IsAlive(wrap)) uv_unref(wrap->GetHandle()); @@ -34,7 +36,8 @@ void HandleWrap::Unref(const FunctionCallbackInfo<Value>& args) { void HandleWrap::HasRef(const FunctionCallbackInfo<Value>& args) { - HandleWrap* wrap = Unwrap<HandleWrap>(args.Holder()); + HandleWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); args.GetReturnValue().Set(HasRef(wrap)); } @@ -42,7 +45,8 @@ void HandleWrap::HasRef(const FunctionCallbackInfo<Value>& args) { void HandleWrap::Close(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - HandleWrap* wrap = Unwrap<HandleWrap>(args.Holder()); + HandleWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); // Guard against uninitialized handle or double close. if (!IsAlive(wrap)) diff --git a/src/js_stream.cc b/src/js_stream.cc index 6ebdb5a356..e51c4ae9b3 100644 --- a/src/js_stream.cc +++ b/src/js_stream.cc @@ -135,7 +135,8 @@ static void FreeCallback(char* data, void* hint) { void JSStream::DoAlloc(const FunctionCallbackInfo<Value>& args) { - JSStream* wrap = Unwrap<JSStream>(args.Holder()); + JSStream* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); uv_buf_t buf; wrap->OnAlloc(args[0]->Int32Value(), &buf); @@ -150,7 +151,8 @@ void JSStream::DoAlloc(const FunctionCallbackInfo<Value>& args) { void JSStream::DoRead(const FunctionCallbackInfo<Value>& args) { - JSStream* wrap = Unwrap<JSStream>(args.Holder()); + JSStream* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); CHECK(Buffer::HasInstance(args[1])); uv_buf_t buf = uv_buf_init(Buffer::Data(args[1]), Buffer::Length(args[1])); @@ -159,8 +161,11 @@ void JSStream::DoRead(const FunctionCallbackInfo<Value>& args) { void JSStream::DoAfterWrite(const FunctionCallbackInfo<Value>& args) { - JSStream* wrap = Unwrap<JSStream>(args.Holder()); - WriteWrap* w = Unwrap<WriteWrap>(args[0].As<Object>()); + JSStream* wrap; + CHECK(args[0]->IsObject()); + WriteWrap* w; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); + ASSIGN_OR_RETURN_UNWRAP(&w, args[0].As<Object>()); wrap->OnAfterWrite(w); } @@ -168,14 +173,17 @@ void JSStream::DoAfterWrite(const FunctionCallbackInfo<Value>& args) { template <class Wrap> void JSStream::Finish(const FunctionCallbackInfo<Value>& args) { - Wrap* w = Unwrap<Wrap>(args[0].As<Object>()); + Wrap* w; + CHECK(args[0]->IsObject()); + ASSIGN_OR_RETURN_UNWRAP(&w, args[0].As<Object>()); w->Done(args[1]->Int32Value()); } void JSStream::ReadBuffer(const FunctionCallbackInfo<Value>& args) { - JSStream* wrap = Unwrap<JSStream>(args.Holder()); + JSStream* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); CHECK(Buffer::HasInstance(args[0])); char* data = Buffer::Data(args[0]); @@ -197,7 +205,8 @@ void JSStream::ReadBuffer(const FunctionCallbackInfo<Value>& args) { void JSStream::EmitEOF(const FunctionCallbackInfo<Value>& args) { - JSStream* wrap = Unwrap<JSStream>(args.Holder()); + JSStream* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); wrap->OnRead(UV_EOF, nullptr); } diff --git a/src/node_contextify.cc b/src/node_contextify.cc index bef7168ada..774871b852 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -343,8 +343,8 @@ class ContextifyContext { static void GlobalPropertyGetterCallback( Local<Name> property, const PropertyCallbackInfo<Value>& args) { - ContextifyContext* ctx = - Unwrap<ContextifyContext>(args.Data().As<Object>()); + ContextifyContext* ctx; + ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Data().As<Object>()); // Stil initializing if (ctx->context_.IsEmpty()) @@ -373,8 +373,8 @@ class ContextifyContext { Local<Name> property, Local<Value> value, const PropertyCallbackInfo<Value>& args) { - ContextifyContext* ctx = - Unwrap<ContextifyContext>(args.Data().As<Object>()); + ContextifyContext* ctx; + ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Data().As<Object>()); // Stil initializing if (ctx->context_.IsEmpty()) @@ -387,8 +387,8 @@ class ContextifyContext { static void GlobalPropertyQueryCallback( Local<Name> property, const PropertyCallbackInfo<Integer>& args) { - ContextifyContext* ctx = - Unwrap<ContextifyContext>(args.Data().As<Object>()); + ContextifyContext* ctx; + ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Data().As<Object>()); // Stil initializing if (ctx->context_.IsEmpty()) @@ -414,8 +414,8 @@ class ContextifyContext { static void GlobalPropertyDeleterCallback( Local<Name> property, const PropertyCallbackInfo<Boolean>& args) { - ContextifyContext* ctx = - Unwrap<ContextifyContext>(args.Data().As<Object>()); + ContextifyContext* ctx; + ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Data().As<Object>()); // Stil initializing if (ctx->context_.IsEmpty()) @@ -430,8 +430,8 @@ class ContextifyContext { static void GlobalPropertyEnumeratorCallback( const PropertyCallbackInfo<Array>& args) { - ContextifyContext* ctx = - Unwrap<ContextifyContext>(args.Data().As<Object>()); + ContextifyContext* ctx; + ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Data().As<Object>()); // Stil initializing if (ctx->context_.IsEmpty()) @@ -806,7 +806,8 @@ class ContextifyScript : public BaseObject { return false; } - ContextifyScript* wrapped_script = Unwrap<ContextifyScript>(args.Holder()); + ContextifyScript* wrapped_script; + ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.Holder(), false); Local<UnboundScript> unbound_script = PersistentToLocal(env->isolate(), wrapped_script->script_); Local<Script> script = unbound_script->BindToCurrentContext(); diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 71e1272e9d..873fbfb410 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -338,7 +338,8 @@ void SecureContext::New(const FunctionCallbackInfo<Value>& args) { void SecureContext::Init(const FunctionCallbackInfo<Value>& args) { - SecureContext* sc = Unwrap<SecureContext>(args.Holder()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); Environment* env = sc->env(); const SSL_METHOD* method = SSLv23_method(); @@ -434,7 +435,8 @@ static BIO* LoadBIO(Environment* env, Local<Value> v) { void SecureContext::SetKey(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - SecureContext* sc = Unwrap<SecureContext>(args.Holder()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); unsigned int len = args.Length(); if (len < 1) { @@ -639,7 +641,8 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx, void SecureContext::SetCert(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - SecureContext* sc = Unwrap<SecureContext>(args.Holder()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); if (args.Length() != 1) { return env->ThrowTypeError("Certificate argument is mandatory"); @@ -680,7 +683,8 @@ void SecureContext::AddCACert(const FunctionCallbackInfo<Value>& args) { bool newCAStore = false; Environment* env = Environment::GetCurrent(args); - SecureContext* sc = Unwrap<SecureContext>(args.Holder()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); ClearErrorOnReturn clear_error_on_return; (void) &clear_error_on_return; // Silence compiler warning. @@ -714,7 +718,8 @@ void SecureContext::AddCACert(const FunctionCallbackInfo<Value>& args) { void SecureContext::AddCRL(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - SecureContext* sc = Unwrap<SecureContext>(args.Holder()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); if (args.Length() != 1) { return env->ThrowTypeError("CRL argument is mandatory"); @@ -745,7 +750,8 @@ void SecureContext::AddCRL(const FunctionCallbackInfo<Value>& args) { void SecureContext::AddRootCerts(const FunctionCallbackInfo<Value>& args) { - SecureContext* sc = Unwrap<SecureContext>(args.Holder()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); ClearErrorOnReturn clear_error_on_return; (void) &clear_error_on_return; // Silence compiler warning. @@ -779,7 +785,8 @@ void SecureContext::AddRootCerts(const FunctionCallbackInfo<Value>& args) { void SecureContext::SetCiphers(const FunctionCallbackInfo<Value>& args) { - SecureContext* sc = Unwrap<SecureContext>(args.Holder()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); Environment* env = sc->env(); ClearErrorOnReturn clear_error_on_return; (void) &clear_error_on_return; // Silence compiler warning. @@ -796,7 +803,8 @@ void SecureContext::SetCiphers(const FunctionCallbackInfo<Value>& args) { void SecureContext::SetECDHCurve(const FunctionCallbackInfo<Value>& args) { - SecureContext* sc = Unwrap<SecureContext>(args.Holder()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); Environment* env = sc->env(); if (args.Length() != 1) @@ -824,7 +832,8 @@ void SecureContext::SetECDHCurve(const FunctionCallbackInfo<Value>& args) { void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) { - SecureContext* sc = Unwrap<SecureContext>(args.This()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.This()); Environment* env = sc->env(); ClearErrorOnReturn clear_error_on_return; (void) &clear_error_on_return; // Silence compiler warning. @@ -863,7 +872,8 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) { void SecureContext::SetOptions(const FunctionCallbackInfo<Value>& args) { - SecureContext* sc = Unwrap<SecureContext>(args.Holder()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); if (args.Length() != 1 || !args[0]->IntegerValue()) { return sc->env()->ThrowTypeError("Options must be an integer value"); @@ -875,7 +885,8 @@ void SecureContext::SetOptions(const FunctionCallbackInfo<Value>& args) { void SecureContext::SetSessionIdContext( const FunctionCallbackInfo<Value>& args) { - SecureContext* sc = Unwrap<SecureContext>(args.Holder()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); Environment* env = sc->env(); if (args.Length() != 1) { @@ -913,7 +924,8 @@ void SecureContext::SetSessionIdContext( void SecureContext::SetSessionTimeout(const FunctionCallbackInfo<Value>& args) { - SecureContext* sc = Unwrap<SecureContext>(args.Holder()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); if (args.Length() != 1 || !args[0]->IsInt32()) { return sc->env()->ThrowTypeError( @@ -926,7 +938,8 @@ void SecureContext::SetSessionTimeout(const FunctionCallbackInfo<Value>& args) { void SecureContext::Close(const FunctionCallbackInfo<Value>& args) { - SecureContext* sc = Unwrap<SecureContext>(args.Holder()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); sc->FreeCTXMem(); } @@ -943,7 +956,8 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) { char* pass = nullptr; bool ret = false; - SecureContext* sc = Unwrap<SecureContext>(args.Holder()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); ClearErrorOnReturn clear_error_on_return; (void) &clear_error_on_return; // Silence compiler warning. @@ -1018,7 +1032,8 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) { void SecureContext::GetTicketKeys(const FunctionCallbackInfo<Value>& args) { #if !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_get_tlsext_ticket_keys) - SecureContext* wrap = Unwrap<SecureContext>(args.Holder()); + SecureContext* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); Local<Object> buff = Buffer::New(wrap->env(), 48).ToLocalChecked(); if (SSL_CTX_get_tlsext_ticket_keys(wrap->ctx_, @@ -1034,7 +1049,8 @@ void SecureContext::GetTicketKeys(const FunctionCallbackInfo<Value>& args) { void SecureContext::SetTicketKeys(const FunctionCallbackInfo<Value>& args) { #if !defined(OPENSSL_NO_TLSEXT) && defined(SSL_CTX_get_tlsext_ticket_keys) - SecureContext* wrap = Unwrap<SecureContext>(args.Holder()); + SecureContext* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); Environment* env = wrap->env(); if (args.Length() < 1) { @@ -1059,7 +1075,8 @@ void SecureContext::SetTicketKeys(const FunctionCallbackInfo<Value>& args) { void SecureContext::SetFreeListLength(const FunctionCallbackInfo<Value>& args) { - SecureContext* wrap = Unwrap<SecureContext>(args.Holder()); + SecureContext* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); wrap->ctx_->freelist_max_len = args[0]->Int32Value(); } @@ -1067,7 +1084,8 @@ void SecureContext::SetFreeListLength(const FunctionCallbackInfo<Value>& args) { void SecureContext::EnableTicketKeyCallback( const FunctionCallbackInfo<Value>& args) { - SecureContext* wrap = Unwrap<SecureContext>(args.Holder()); + SecureContext* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); SSL_CTX_set_tlsext_ticket_key_cb(wrap->ctx_, TicketKeyCallback); } @@ -1156,15 +1174,17 @@ int SecureContext::TicketKeyCallback(SSL* ssl, void SecureContext::CtxGetter(Local<String> property, const PropertyCallbackInfo<Value>& info) { - SSL_CTX* ctx = Unwrap<SecureContext>(info.This())->ctx_; - Local<External> ext = External::New(info.GetIsolate(), ctx); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, info.This()); + Local<External> ext = External::New(info.GetIsolate(), sc->ctx_); info.GetReturnValue().Set(ext); } template <bool primary> void SecureContext::GetCertificate(const FunctionCallbackInfo<Value>& args) { - SecureContext* wrap = Unwrap<SecureContext>(args.Holder()); + SecureContext* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); Environment* env = wrap->env(); X509* cert; @@ -1543,7 +1563,8 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) { template <class Base> void SSLWrap<Base>::GetPeerCertificate( const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = w->ssl_env(); ClearErrorOnReturn clear_error_on_return; @@ -1651,7 +1672,8 @@ template <class Base> void SSLWrap<Base>::GetSession(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); SSL_SESSION* sess = SSL_get_session(w->ssl_); if (sess == nullptr) @@ -1672,7 +1694,8 @@ template <class Base> void SSLWrap<Base>::SetSession(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); if (args.Length() < 1) { return env->ThrowError("Session argument is mandatory"); @@ -1701,7 +1724,8 @@ void SSLWrap<Base>::SetSession(const FunctionCallbackInfo<Value>& args) { template <class Base> void SSLWrap<Base>::LoadSession(const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = w->ssl_env(); if (args.Length() >= 1 && Buffer::HasInstance(args[0])) { @@ -1732,7 +1756,8 @@ void SSLWrap<Base>::LoadSession(const FunctionCallbackInfo<Value>& args) { template <class Base> void SSLWrap<Base>::IsSessionReused(const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); bool yes = SSL_session_reused(w->ssl_); args.GetReturnValue().Set(yes); } @@ -1740,14 +1765,16 @@ void SSLWrap<Base>::IsSessionReused(const FunctionCallbackInfo<Value>& args) { template <class Base> void SSLWrap<Base>::EndParser(const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); w->hello_parser_.End(); } template <class Base> void SSLWrap<Base>::Renegotiate(const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); ClearErrorOnReturn clear_error_on_return; (void) &clear_error_on_return; // Silence unused variable warning. @@ -1759,7 +1786,8 @@ void SSLWrap<Base>::Renegotiate(const FunctionCallbackInfo<Value>& args) { template <class Base> void SSLWrap<Base>::Shutdown(const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); int rv = SSL_shutdown(w->ssl_); args.GetReturnValue().Set(rv); @@ -1768,7 +1796,8 @@ void SSLWrap<Base>::Shutdown(const FunctionCallbackInfo<Value>& args) { template <class Base> void SSLWrap<Base>::GetTLSTicket(const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = w->ssl_env(); SSL_SESSION* sess = SSL_get_session(w->ssl_); @@ -1786,7 +1815,8 @@ void SSLWrap<Base>::GetTLSTicket(const FunctionCallbackInfo<Value>& args) { template <class Base> void SSLWrap<Base>::NewSessionDone(const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); w->new_session_wait_ = false; w->NewSessionDoneCb(); } @@ -1798,7 +1828,8 @@ void SSLWrap<Base>::SetOCSPResponse( #ifdef NODE__HAVE_TLSEXT_STATUS_CB HandleScope scope(args.GetIsolate()); - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = w->env(); if (args.Length() < 1) @@ -1817,7 +1848,8 @@ void SSLWrap<Base>::RequestOCSP( #ifdef NODE__HAVE_TLSEXT_STATUS_CB HandleScope scope(args.GetIsolate()); - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); SSL_set_tlsext_status_type(w->ssl_, TLSEXT_STATUSTYPE_ocsp); #endif // NODE__HAVE_TLSEXT_STATUS_CB @@ -1827,7 +1859,8 @@ void SSLWrap<Base>::RequestOCSP( template <class Base> void SSLWrap<Base>::GetEphemeralKeyInfo( const v8::FunctionCallbackInfo<v8::Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = Environment::GetCurrent(args); CHECK_NE(w->ssl_, nullptr); @@ -1875,7 +1908,8 @@ void SSLWrap<Base>::SetMaxSendFragment( HandleScope scope(args.GetIsolate()); CHECK(args.Length() >= 1 && args[0]->IsNumber()); - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); int rv = SSL_set_max_send_fragment(w->ssl_, args[0]->Int32Value()); args.GetReturnValue().Set(rv); @@ -1885,7 +1919,8 @@ void SSLWrap<Base>::SetMaxSendFragment( template <class Base> void SSLWrap<Base>::IsInitFinished(const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); bool yes = SSL_is_init_finished(w->ssl_); args.GetReturnValue().Set(yes); } @@ -1893,7 +1928,8 @@ void SSLWrap<Base>::IsInitFinished(const FunctionCallbackInfo<Value>& args) { template <class Base> void SSLWrap<Base>::VerifyError(const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); // XXX(bnoordhuis) The UNABLE_TO_GET_ISSUER_CERT error when there is no // peer certificate is questionable but it's compatible with what was @@ -1956,7 +1992,8 @@ void SSLWrap<Base>::VerifyError(const FunctionCallbackInfo<Value>& args) { template <class Base> void SSLWrap<Base>::GetCurrentCipher(const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = w->ssl_env(); const SSL_CIPHER* c = SSL_get_current_cipher(w->ssl_); @@ -1975,7 +2012,8 @@ void SSLWrap<Base>::GetCurrentCipher(const FunctionCallbackInfo<Value>& args) { template <class Base> void SSLWrap<Base>::GetProtocol(const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); const char* tls_version = SSL_get_version(w->ssl_); args.GetReturnValue().Set(OneByteString(args.GetIsolate(), tls_version)); @@ -2079,7 +2117,8 @@ int SSLWrap<Base>::SelectNextProtoCallback(SSL* s, template <class Base> void SSLWrap<Base>::GetNegotiatedProto( const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = w->env(); if (w->is_client()) { @@ -2106,7 +2145,8 @@ void SSLWrap<Base>::GetNegotiatedProto( template <class Base> void SSLWrap<Base>::SetNPNProtocols(const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = w->env(); if (args.Length() < 1) @@ -2173,7 +2213,8 @@ void SSLWrap<Base>::GetALPNNegotiatedProto( const FunctionCallbackInfo<v8::Value>& args) { #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation HandleScope scope(args.GetIsolate()); - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); const unsigned char* alpn_proto; unsigned int alpn_proto_len; @@ -2194,7 +2235,8 @@ void SSLWrap<Base>::SetALPNProtocols( const FunctionCallbackInfo<v8::Value>& args) { #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation HandleScope scope(args.GetIsolate()); - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = w->env(); if (args.Length() < 1 || !Buffer::HasInstance(args[0])) return env->ThrowTypeError("Must give a Buffer as first argument"); @@ -2328,7 +2370,8 @@ int SSLWrap<Base>::SSLCertCallback(SSL* s, void* arg) { template <class Base> void SSLWrap<Base>::CertCbDone(const FunctionCallbackInfo<Value>& args) { - Base* w = Unwrap<Base>(args.Holder()); + Base* w; + ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); Environment* env = w->env(); CHECK(w->is_waiting_cert_cb() && w->cert_cb_running_); @@ -2342,7 +2385,8 @@ void SSLWrap<Base>::CertCbDone(const FunctionCallbackInfo<Value>& args) { goto fire_cb; if (cons->HasInstance(ctx)) { - SecureContext* sc = Unwrap<SecureContext>(ctx.As<Object>()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, ctx.As<Object>()); w->sni_context_.Reset(); w->sni_context_.Reset(env->isolate(), ctx); @@ -2393,7 +2437,9 @@ void SSLWrap<Base>::CertCbDone(const FunctionCallbackInfo<Value>& args) { template <class Base> void SSLWrap<Base>::SSLGetter(Local<String> property, const PropertyCallbackInfo<Value>& info) { - SSL* ssl = Unwrap<Base>(info.This())->ssl_; + Base* base; + ASSIGN_OR_RETURN_UNWRAP(&base, info.This()); + SSL* ssl = base->ssl_; Local<External> ext = External::New(info.GetIsolate(), ssl); info.GetReturnValue().Set(ext); } @@ -2746,7 +2792,8 @@ int Connection::SelectSNIContextCallback_(SSL *s, int *ad, void* arg) { env->secure_context_constructor_template(); if (secure_context_constructor_template->HasInstance(ret)) { conn->sni_context_.Reset(env->isolate(), ret); - SecureContext* sc = Unwrap<SecureContext>(ret.As<Object>()); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, ret.As<Object>(), SSL_TLSEXT_ERR_NOACK); conn->SetSNIContext(sc); } else { return SSL_TLSEXT_ERR_NOACK; @@ -2766,7 +2813,8 @@ void Connection::New(const FunctionCallbackInfo<Value>& args) { return; } - SecureContext* sc = Unwrap<SecureContext>(args[0]->ToObject(env->isolate())); + SecureContext* sc; + ASSIGN_OR_RETURN_UNWRAP(&sc, args[0].As<Object>()); bool is_server = args[1]->BooleanValue(); @@ -2854,7 +2902,8 @@ void Connection::SSLInfoCallback(const SSL *ssl_, int where, int ret) { void Connection::EncIn(const FunctionCallbackInfo<Value>& args) { - Connection* conn = Unwrap<Connection>(args.Holder()); + Connection* conn; + ASSIGN_OR_RETURN_UNWRAP(&conn, args.Holder()); Environment* env = conn->env(); if (args.Length() < 3) { @@ -2902,7 +2951,8 @@ void Connection::EncIn(const FunctionCallbackInfo<Value>& args) { void Connection::ClearOut(const FunctionCallbackInfo<Value>& args) { - Connection* conn = Unwrap<Connection>(args.Holder()); + Connection* conn; + ASSIGN_OR_RETURN_UNWRAP(&conn, args.Holder()); Environment* env = conn->env(); if (args.Length() < 3) { @@ -2955,21 +3005,24 @@ void Connection::ClearOut(const FunctionCallbackInfo<Value>& args) { void Connection::ClearPending(const FunctionCallbackInfo<Value>& args) { - Connection* conn = Unwrap<Connection>(args.Holder()); + Connection* conn; + ASSIGN_OR_RETURN_UNWRAP(&conn, args.Holder()); int bytes_pending = BIO_pending(conn->bio_read_); args.GetReturnValue().Set(bytes_pending); } void Connection::EncPending(const FunctionCallbackInfo<Value>& args) { - Connection* conn = Unwrap<Connection>(args.Holder()); + Connection* conn; + ASSIGN_OR_RETURN_UNWRAP(&conn, args.Holder()); int bytes_pending = BIO_pending(conn->bio_write_); args.GetReturnValue().Set(bytes_pending); } void Connection::EncOut(const FunctionCallbackInfo<Value>& args) { - Connection* conn = Unwrap<Connection>(args.Holder()); + Connection* conn; + ASSIGN_OR_RETURN_UNWRAP(&conn, args.Holder()); Environment* env = conn->env(); if (args.Length() < 3) { @@ -2998,7 +3051,8 @@ void Connection::EncOut(const FunctionCallbackInfo<Value>& args) { void Connection::ClearIn(const FunctionCallbackInfo<Value>& args) { - Connection* conn = Unwrap<Connection>(args.Holder()); + Connection* conn; + ASSIGN_OR_RETURN_UNWRAP(&conn, args.Holder()); Environment* env = conn->env(); if (args.Length() < 3) { @@ -3051,7 +3105,8 @@ void Connection::ClearIn(const FunctionCallbackInfo<Value>& args) { void Connection::Start(const FunctionCallbackInfo<Value>& args) { - Connection* conn = Unwrap<Connection>(args.Holder()); + Connection* conn; + ASSIGN_OR_RETURN_UNWRAP(&conn, args.Holder()); int rv = 0; if (!SSL_is_init_finished(conn->ssl_)) { @@ -3074,7 +3129,8 @@ void Connection::Start(const FunctionCallbackInfo<Value>& args) { void Connection::Close(const FunctionCallbackInfo<Value>& args) { - Connection* conn = Unwrap<Connection>(args.Holder()); + Connection* conn; + ASSIGN_OR_RETURN_UNWRAP(&conn, args.Holder()); if (conn->ssl_ != nullptr) { SSL_free(conn->ssl_); @@ -3085,7 +3141,8 @@ void Connection::Close(const FunctionCallbackInfo<Value>& args) { #ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB void Connection::GetServername(const FunctionCallbackInfo<Value>& args) { - Connection* conn = Unwrap<Connection>(args.Holder()); + Connection* conn; + ASSIGN_OR_RETURN_UNWRAP(&conn, args.Holder()); if (conn->is_server() && !conn->servername_.IsEmpty()) { args.GetReturnValue().Set(conn->servername_); @@ -3096,7 +3153,8 @@ void Connection::GetServername(const FunctionCallbackInfo<Value>& args) { void Connection::SetSNICallback(const FunctionCallbackInfo<Value>& args) { - Connection* conn = Unwrap<Connection>(args.Holder()); + Connection* conn; + ASSIGN_OR_RETURN_UNWRAP(&conn, args.Holder()); Environment* env = conn->env(); if (args.Length() < 1 || !args[0]->IsFunction()) { @@ -3186,7 +3244,8 @@ void CipherBase::Init(const char* cipher_type, void CipherBase::Init(const FunctionCallbackInfo<Value>& args) { - CipherBase* cipher = Unwrap<CipherBase>(args.Holder()); + CipherBase* cipher; + ASSIGN_OR_RETURN_UNWRAP(&cipher, args.Holder()); Environment* env = cipher->env(); if (args.Length() < 2) { @@ -3240,7 +3299,8 @@ void CipherBase::InitIv(const char* cipher_type, void CipherBase::InitIv(const FunctionCallbackInfo<Value>& args) { - CipherBase* cipher = Unwrap<CipherBase>(args.Holder()); + CipherBase* cipher; + ASSIGN_OR_RETURN_UNWRAP(&cipher, args.Holder()); Environment* env = cipher->env(); if (args.Length() < 3) { @@ -3283,7 +3343,8 @@ bool CipherBase::GetAuthTag(char** out, unsigned int* out_len) const { void CipherBase::GetAuthTag(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - CipherBase* cipher = Unwrap<CipherBase>(args.Holder()); + CipherBase* cipher; + ASSIGN_OR_RETURN_UNWRAP(&cipher, args.Holder()); char* out = nullptr; unsigned int out_len = 0; @@ -3316,7 +3377,8 @@ void CipherBase::SetAuthTag(const FunctionCallbackInfo<Value>& args) { if (!buf->IsObject() || !Buffer::HasInstance(buf)) return env->ThrowTypeError("Auth tag must be a Buffer"); - CipherBase* cipher = Unwrap<CipherBase>(args.Holder()); + CipherBase* cipher; + ASSIGN_OR_RETURN_UNWRAP(&cipher, args.Holder()); if (!cipher->SetAuthTag(Buffer::Data(buf), Buffer::Length(buf))) env->ThrowError("Attempting to set auth tag in unsupported state"); @@ -3343,7 +3405,8 @@ void CipherBase::SetAAD(const FunctionCallbackInfo<Value>& args) { THROW_AND_RETURN_IF_NOT_BUFFER(args[0], "AAD"); - CipherBase* cipher = Unwrap<CipherBase>(args.Holder()); + CipherBase* cipher; + ASSIGN_OR_RETURN_UNWRAP(&cipher, args.Holder()); if (!cipher->SetAAD(Buffer::Data(args[0]), Buffer::Length(args[0]))) env->ThrowError("Attempting to set AAD in unsupported state"); @@ -3380,7 +3443,8 @@ bool CipherBase::Update(const char* data, void CipherBase::Update(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - CipherBase* cipher = Unwrap<CipherBase>(args.Holder()); + CipherBase* cipher; + ASSIGN_OR_RETURN_UNWRAP(&cipher, args.Holder()); THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(args[0], "Cipher data"); @@ -3425,7 +3489,8 @@ bool CipherBase::SetAutoPadding(bool auto_padding) { void CipherBase::SetAutoPadding(const FunctionCallbackInfo<Value>& args) { - CipherBase* cipher = Unwrap<CipherBase>(args.Holder()); + CipherBase* cipher; + ASSIGN_OR_RETURN_UNWRAP(&cipher, args.Holder()); cipher->SetAutoPadding(args.Length() < 1 || args[0]->BooleanValue()); } @@ -3461,7 +3526,8 @@ bool CipherBase::Final(unsigned char** out, int *out_len) { void CipherBase::Final(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - CipherBase* cipher = Unwrap<CipherBase>(args.Holder()); + CipherBase* cipher; + ASSIGN_OR_RETURN_UNWRAP(&cipher, args.Holder()); unsigned char* out_value = nullptr; int out_len = -1; @@ -3535,7 +3601,8 @@ void Hmac::HmacInit(const char* hash_type, const char* key, int key_len) { void Hmac::HmacInit(const FunctionCallbackInfo<Value>& args) { - Hmac* hmac = Unwrap<Hmac>(args.Holder()); + Hmac* hmac; + ASSIGN_OR_RETURN_UNWRAP(&hmac, args.Holder()); Environment* env = hmac->env(); if (args.Length() < 2) { @@ -3563,7 +3630,8 @@ bool Hmac::HmacUpdate(const char* data, int len) { void Hmac::HmacUpdate(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - Hmac* hmac = Unwrap<Hmac>(args.Holder()); + Hmac* hmac; + ASSIGN_OR_RETURN_UNWRAP(&hmac, args.Holder()); THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(args[0], "Data"); @@ -3600,7 +3668,8 @@ bool Hmac::HmacDigest(unsigned char** md_value, unsigned int* md_len) { void Hmac::HmacDigest(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - Hmac* hmac = Unwrap<Hmac>(args.Holder()); + Hmac* hmac; + ASSIGN_OR_RETURN_UNWRAP(&hmac, args.Holder()); enum encoding encoding = BUFFER; if (args.Length() >= 1) { @@ -3682,7 +3751,8 @@ bool Hash::HashUpdate(const char* data, int len) { void Hash::HashUpdate(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - Hash* hash = Unwrap<Hash>(args.Holder()); + Hash* hash; + ASSIGN_OR_RETURN_UNWRAP(&hash, args.Holder()); THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(args[0], "Data"); @@ -3715,7 +3785,8 @@ void Hash::HashUpdate(const FunctionCallbackInfo<Value>& args) { void Hash::HashDigest(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - Hash* hash = Unwrap<Hash>(args.Holder()); + Hash* hash; + ASSIGN_OR_RETURN_UNWRAP(&hash, args.Holder()); if (!hash->initialised_) { return env->ThrowError("Not initialized"); @@ -3821,7 +3892,8 @@ SignBase::Error Sign::SignInit(const char* sign_type) { void Sign::SignInit(const FunctionCallbackInfo<Value>& args) { - Sign* sign = Unwrap<Sign>(args.Holder()); + Sign* sign; + ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder()); Environment* env = sign->env(); if (args.Length() == 0) { @@ -3847,7 +3919,8 @@ SignBase::Error Sign::SignUpdate(const char* data, int len) { void Sign::SignUpdate(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - Sign* sign = Unwrap<Sign>(args.Holder()); + Sign* sign; + ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder()); THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(args[0], "Data"); @@ -3941,7 +4014,8 @@ SignBase::Error Sign::SignFinal(const char* key_pem, void Sign::SignFinal(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - Sign* sign = Unwrap<Sign>(args.Holder()); + Sign* sign; + ASSIGN_OR_RETURN_UNWRAP(&sign, args.Holder()); unsigned char* md_value; unsigned int md_len; @@ -4024,7 +4098,8 @@ SignBase::Error Verify::VerifyInit(const char* verify_type) { void Verify::VerifyInit(const FunctionCallbackInfo<Value>& args) { - Verify* verify = Unwrap<Verify>(args.Holder()); + Verify* verify; + ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder()); Environment* env = verify->env(); if (args.Length() == 0) { @@ -4052,7 +4127,8 @@ SignBase::Error Verify::VerifyUpdate(const char* data, int len) { void Verify::VerifyUpdate(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - Verify* verify = Unwrap<Verify>(args.Holder()); + Verify* verify; + ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder()); THROW_AND_RETURN_IF_NOT_STRING_OR_BUFFER(args[0], "Data"); @@ -4151,7 +4227,8 @@ SignBase::Error Verify::VerifyFinal(const char* key_pem, void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - Verify* verify = Unwrap<Verify>(args.Holder()); + Verify* verify; + ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder()); THROW_AND_RETURN_IF_NOT_BUFFER(args[0], "Key"); char* kbuf = Buffer::Data(args[0]); @@ -4493,7 +4570,8 @@ void DiffieHellman::New(const FunctionCallbackInfo<Value>& args) { void DiffieHellman::GenerateKeys(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - DiffieHellman* diffieHellman = Unwrap<DiffieHellman>(args.Holder()); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.Holder()); if (!diffieHellman->initialised_) { return ThrowCryptoError(env, ERR_get_error(), "Not initialized"); @@ -4516,7 +4594,8 @@ void DiffieHellman::GenerateKeys(const FunctionCallbackInfo<Value>& args) { void DiffieHellman::GetPrime(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - DiffieHellman* diffieHellman = Unwrap<DiffieHellman>(args.Holder()); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.Holder()); if (!diffieHellman->initialised_) { return ThrowCryptoError(env, ERR_get_error(), "Not initialized"); @@ -4534,7 +4613,8 @@ void DiffieHellman::GetPrime(const FunctionCallbackInfo<Value>& args) { void DiffieHellman::GetGenerator(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - DiffieHellman* diffieHellman = Unwrap<DiffieHellman>(args.Holder()); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.Holder()); if (!diffieHellman->initialised_) { return ThrowCryptoError(env, ERR_get_error(), "Not initialized"); @@ -4552,7 +4632,8 @@ void DiffieHellman::GetGenerator(const FunctionCallbackInfo<Value>& args) { void DiffieHellman::GetPublicKey(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - DiffieHellman* diffieHellman = Unwrap<DiffieHellman>(args.Holder()); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.Holder()); if (!diffieHellman->initialised_) { return ThrowCryptoError(env, ERR_get_error(), "Not initialized"); @@ -4575,7 +4656,8 @@ void DiffieHellman::GetPublicKey(const FunctionCallbackInfo<Value>& args) { void DiffieHellman::GetPrivateKey(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - DiffieHellman* diffieHellman = Unwrap<DiffieHellman>(args.Holder()); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.Holder()); if (!diffieHellman->initialised_) { return ThrowCryptoError(env, ERR_get_error(), "Not initialized"); @@ -4598,7 +4680,8 @@ void DiffieHellman::GetPrivateKey(const FunctionCallbackInfo<Value>& args) { void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - DiffieHellman* diffieHellman = Unwrap<DiffieHellman>(args.Holder()); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.Holder()); if (!diffieHellman->initialised_) { return ThrowCryptoError(env, ERR_get_error(), "Not initialized"); @@ -4667,7 +4750,8 @@ void DiffieHellman::ComputeSecret(const FunctionCallbackInfo<Value>& args) { void DiffieHellman::SetPublicKey(const FunctionCallbackInfo<Value>& args) { - DiffieHellman* diffieHellman = Unwrap<DiffieHellman>(args.Holder()); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.Holder()); Environment* env = diffieHellman->env(); if (!diffieHellman->initialised_) { @@ -4686,7 +4770,8 @@ void DiffieHellman::SetPublicKey(const FunctionCallbackInfo<Value>& args) { void DiffieHellman::SetPrivateKey(const FunctionCallbackInfo<Value>& args) { - DiffieHellman* diffieHellman = Unwrap<DiffieHellman>(args.Holder()); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.Holder()); Environment* env = diffieHellman->env(); if (!diffieHellman->initialised_) { @@ -4709,7 +4794,8 @@ void DiffieHellman::VerifyErrorGetter(Local<String> property, const PropertyCallbackInfo<Value>& args) { HandleScope scope(args.GetIsolate()); - DiffieHellman* diffieHellman = Unwrap<DiffieHellman>(args.Holder()); + DiffieHellman* diffieHellman; + ASSIGN_OR_RETURN_UNWRAP(&diffieHellman, args.Holder()); if (!diffieHellman->initialised_) return ThrowCryptoError(diffieHellman->env(), ERR_get_error(), @@ -4771,7 +4857,8 @@ void ECDH::New(const FunctionCallbackInfo<Value>& args) { void ECDH::GenerateKeys(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - ECDH* ecdh = Unwrap<ECDH>(args.Holder()); + ECDH* ecdh; + ASSIGN_OR_RETURN_UNWRAP(&ecdh, args.Holder()); if (!EC_KEY_generate_key(ecdh->key_)) return env->ThrowError("Failed to generate EC_KEY"); @@ -4812,7 +4899,8 @@ void ECDH::ComputeSecret(const FunctionCallbackInfo<Value>& args) { THROW_AND_RETURN_IF_NOT_BUFFER(args[0], "Data"); - ECDH* ecdh = Unwrap<ECDH>(args.Holder()); + ECDH* ecdh; + ASSIGN_OR_RETURN_UNWRAP(&ecdh, args.Holder()); if (!ecdh->IsKeyPairValid()) return env->ThrowError("Invalid key pair"); @@ -4846,7 +4934,8 @@ void ECDH::GetPublicKey(const FunctionCallbackInfo<Value>& args) { // Conversion form CHECK_EQ(args.Length(), 1); - ECDH* ecdh = Unwrap<ECDH>(args.Holder()); + ECDH* ecdh; + ASSIGN_OR_RETURN_UNWRAP(&ecdh, args.Holder()); const EC_POINT* pub = EC_KEY_get0_public_key(ecdh->key_); if (pub == nullptr) @@ -4878,7 +4967,8 @@ void ECDH::GetPublicKey(const FunctionCallbackInfo<Value>& args) { void ECDH::GetPrivateKey(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - ECDH* ecdh = Unwrap<ECDH>(args.Holder()); + ECDH* ecdh; + ASSIGN_OR_RETURN_UNWRAP(&ecdh, args.Holder()); const BIGNUM* b = EC_KEY_get0_private_key(ecdh->key_); if (b == nullptr) @@ -4902,7 +4992,8 @@ void ECDH::GetPrivateKey(const FunctionCallbackInfo<Value>& args) { void ECDH::SetPrivateKey(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - ECDH* ecdh = Unwrap<ECDH>(args.Holder()); + ECDH* ecdh; + ASSIGN_OR_RETURN_UNWRAP(&ecdh, args.Holder()); THROW_AND_RETURN_IF_NOT_BUFFER(args[0], "Private key"); @@ -4955,7 +5046,8 @@ void ECDH::SetPrivateKey(const FunctionCallbackInfo<Value>& args) { void ECDH::SetPublicKey(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - ECDH* ecdh = Unwrap<ECDH>(args.Holder()); + ECDH* ecdh; + ASSIGN_OR_RETURN_UNWRAP(&ecdh, args.Holder()); THROW_AND_RETURN_IF_NOT_BUFFER(args[0], "Public key"); diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index 4a0dd580a4..fd5e7c8e21 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -368,7 +368,8 @@ class Parser : public AsyncWrap { static void Close(const FunctionCallbackInfo<Value>& args) { - Parser* parser = Unwrap<Parser>(args.Holder()); + Parser* parser; + ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder()); if (--parser->refcount_ == 0) delete parser; @@ -391,7 +392,8 @@ class Parser : public AsyncWrap { // var bytesParsed = parser->execute(buffer); static void Execute(const FunctionCallbackInfo<Value>& args) { - Parser* parser = Unwrap<Parser>(args.Holder()); + Parser* parser; + ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder()); CHECK(parser->current_buffer_.IsEmpty()); CHECK_EQ(parser->current_buffer_len_, 0); CHECK_EQ(parser->current_buffer_data_, nullptr); @@ -416,7 +418,8 @@ class Parser : public AsyncWrap { static void Finish(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - Parser* parser = Unwrap<Parser>(args.Holder()); + Parser* parser; + ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder()); CHECK(parser->current_buffer_.IsEmpty()); parser->got_exception_ = false; @@ -447,7 +450,8 @@ class Parser : public AsyncWrap { static_cast<http_parser_type>(args[0]->Int32Value()); CHECK(type == HTTP_REQUEST || type == HTTP_RESPONSE); - Parser* parser = Unwrap<Parser>(args.Holder()); + Parser* parser; + ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder()); // Should always be called from the same context. CHECK_EQ(env, parser->env()); parser->Init(type); @@ -457,7 +461,8 @@ class Parser : public AsyncWrap { template <bool should_pause> static void Pause(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - Parser* parser = Unwrap<Parser>(args.Holder()); + Parser* parser; + ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder()); // Should always be called from the same context. CHECK_EQ(env, parser->env()); http_parser_pause(&parser->parser_, should_pause); @@ -465,7 +470,8 @@ class Parser : public AsyncWrap { static void Consume(const FunctionCallbackInfo<Value>& args) { - Parser* parser = Unwrap<Parser>(args.Holder()); + Parser* parser; + ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder()); Local<External> stream_obj = args[0].As<External>(); StreamBase* stream = static_cast<StreamBase*>(stream_obj->Value()); CHECK_NE(stream, nullptr); @@ -481,7 +487,8 @@ class Parser : public AsyncWrap { static void Unconsume(const FunctionCallbackInfo<Value>& args) { - Parser* parser = Unwrap<Parser>(args.Holder()); + Parser* parser; + ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder()); // Already unconsumed if (parser->prev_alloc_cb_.is_empty()) @@ -503,7 +510,8 @@ class Parser : public AsyncWrap { static void GetCurrentBuffer(const FunctionCallbackInfo<Value>& args) { - Parser* parser = Unwrap<Parser>(args.Holder()); + Parser* parser; + ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder()); Local<Object> ret = Buffer::Copy( parser->env(), diff --git a/src/node_internals.h b/src/node_internals.h index 0d660705c8..a46d3130bf 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -85,6 +85,8 @@ v8::Local<v8::Object> AddressToJS( template <typename T, int (*F)(const typename T::HandleType*, sockaddr*, int*)> void GetSockOrPeerName(const v8::FunctionCallbackInfo<v8::Value>& args) { T* const wrap = Unwrap<T>(args.Holder()); + if (wrap == nullptr) + return args.GetReturnValue().Set(UV_EBADF); CHECK(args[0]->IsObject()); sockaddr_storage storage; int addrlen = sizeof(storage); diff --git a/src/node_stat_watcher.cc b/src/node_stat_watcher.cc index 4fa01794f6..cff92e3404 100644 --- a/src/node_stat_watcher.cc +++ b/src/node_stat_watcher.cc @@ -84,7 +84,8 @@ void StatWatcher::New(const FunctionCallbackInfo<Value>& args) { void StatWatcher::Start(const FunctionCallbackInfo<Value>& args) { CHECK_EQ(args.Length(), 3); - StatWatcher* wrap = Unwrap<StatWatcher>(args.Holder()); + StatWatcher* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); node::Utf8Value path(args.GetIsolate(), args[0]); const bool persistent = args[1]->BooleanValue(); const uint32_t interval = args[2]->Uint32Value(); @@ -97,7 +98,8 @@ void StatWatcher::Start(const FunctionCallbackInfo<Value>& args) { void StatWatcher::Stop(const FunctionCallbackInfo<Value>& args) { - StatWatcher* wrap = Unwrap<StatWatcher>(args.Holder()); + StatWatcher* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); Environment* env = wrap->env(); Context::Scope context_scope(env->context()); wrap->MakeCallback(env->onstop_string(), 0, nullptr); diff --git a/src/node_wrap.h b/src/node_wrap.h index d508a4a470..b2d6af8ad5 100644 --- a/src/node_wrap.h +++ b/src/node_wrap.h @@ -39,6 +39,8 @@ inline uv_stream_t* HandleToStream(Environment* env, v8::HandleScope scope(env->isolate()); WITH_GENERIC_UV_STREAM(env, obj, { + if (wrap == nullptr) + return nullptr; return reinterpret_cast<uv_stream_t*>(wrap->UVHandle()); }, {}); diff --git a/src/node_zlib.cc b/src/node_zlib.cc index aee1cbae95..4de9d7cdc2 100644 --- a/src/node_zlib.cc +++ b/src/node_zlib.cc @@ -109,7 +109,8 @@ class ZCtx : public AsyncWrap { static void Close(const FunctionCallbackInfo<Value>& args) { - ZCtx* ctx = Unwrap<ZCtx>(args.Holder()); + ZCtx* ctx; + ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder()); ctx->Close(); } @@ -119,7 +120,8 @@ class ZCtx : public AsyncWrap { static void Write(const FunctionCallbackInfo<Value>& args) { CHECK_EQ(args.Length(), 7); - ZCtx* ctx = Unwrap<ZCtx>(args.Holder()); + ZCtx* ctx; + ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder()); CHECK(ctx->init_done_ && "write before init"); CHECK(ctx->mode_ != NONE && "already finalized"); @@ -431,7 +433,8 @@ class ZCtx : public AsyncWrap { CHECK((args.Length() == 4 || args.Length() == 5) && "init(windowBits, level, memLevel, strategy, [dictionary])"); - ZCtx* ctx = Unwrap<ZCtx>(args.Holder()); + ZCtx* ctx; + ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder()); int windowBits = args[0]->Uint32Value(); CHECK((windowBits >= 8 && windowBits <= 15) && "invalid windowBits"); @@ -467,12 +470,14 @@ class ZCtx : public AsyncWrap { static void Params(const FunctionCallbackInfo<Value>& args) { CHECK(args.Length() == 2 && "params(level, strategy)"); - ZCtx* ctx = Unwrap<ZCtx>(args.Holder()); + ZCtx* ctx; + ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder()); Params(ctx, args[0]->Int32Value(), args[1]->Int32Value()); } static void Reset(const FunctionCallbackInfo<Value> &args) { - ZCtx* ctx = Unwrap<ZCtx>(args.Holder()); + ZCtx* ctx; + ASSIGN_OR_RETURN_UNWRAP(&ctx, args.Holder()); Reset(ctx); SetDictionary(ctx); } diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index 7be07de74b..286ea30a87 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -138,7 +138,8 @@ PipeWrap::PipeWrap(Environment* env, void PipeWrap::Bind(const FunctionCallbackInfo<Value>& args) { - PipeWrap* wrap = Unwrap<PipeWrap>(args.Holder()); + PipeWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); node::Utf8Value name(args.GetIsolate(), args[0]); int err = uv_pipe_bind(&wrap->handle_, *name); args.GetReturnValue().Set(err); @@ -147,7 +148,8 @@ void PipeWrap::Bind(const FunctionCallbackInfo<Value>& args) { #ifdef _WIN32 void PipeWrap::SetPendingInstances(const FunctionCallbackInfo<Value>& args) { - PipeWrap* wrap = Unwrap<PipeWrap>(args.Holder()); + PipeWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); int instances = args[0]->Int32Value(); uv_pipe_pending_instances(&wrap->handle_, instances); } @@ -155,7 +157,8 @@ void PipeWrap::SetPendingInstances(const FunctionCallbackInfo<Value>& args) { void PipeWrap::Listen(const FunctionCallbackInfo<Value>& args) { - PipeWrap* wrap = Unwrap<PipeWrap>(args.Holder()); + PipeWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); int backlog = args[0]->Int32Value(); int err = uv_listen(reinterpret_cast<uv_stream_t*>(&wrap->handle_), backlog, @@ -191,7 +194,8 @@ void PipeWrap::OnConnection(uv_stream_t* handle, int status) { Local<Object> client_obj = Instantiate(env, pipe_wrap); // Unwrap the client javascript object. - PipeWrap* wrap = Unwrap<PipeWrap>(client_obj); + PipeWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, client_obj); uv_stream_t* client_handle = reinterpret_cast<uv_stream_t*>(&wrap->handle_); if (uv_accept(handle, client_handle)) return; @@ -242,7 +246,8 @@ void PipeWrap::AfterConnect(uv_connect_t* req, int status) { void PipeWrap::Open(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - PipeWrap* wrap = Unwrap<PipeWrap>(args.Holder()); + PipeWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); int fd = args[0]->Int32Value(); @@ -256,7 +261,8 @@ void PipeWrap::Open(const FunctionCallbackInfo<Value>& args) { void PipeWrap::Connect(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - PipeWrap* wrap = Unwrap<PipeWrap>(args.Holder()); + PipeWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); CHECK(args[0]->IsObject()); CHECK(args[1]->IsString()); diff --git a/src/process_wrap.cc b/src/process_wrap.cc index 36c6cfe3ad..2b214d1d47 100644 --- a/src/process_wrap.cc +++ b/src/process_wrap.cc @@ -86,6 +86,7 @@ class ProcessWrap : public HandleWrap { UV_CREATE_PIPE | UV_READABLE_PIPE | UV_WRITABLE_PIPE); Local<String> handle_key = env->handle_string(); Local<Object> handle = stdio->Get(handle_key).As<Object>(); + CHECK(!handle.IsEmpty()); options->stdio[i].data.stream = reinterpret_cast<uv_stream_t*>( Unwrap<PipeWrap>(handle)->UVHandle()); @@ -109,7 +110,8 @@ class ProcessWrap : public HandleWrap { static void Spawn(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - ProcessWrap* wrap = Unwrap<ProcessWrap>(args.Holder()); + ProcessWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); Local<Object> js_options = args[0]->ToObject(env->isolate()); @@ -233,7 +235,8 @@ class ProcessWrap : public HandleWrap { } static void Kill(const FunctionCallbackInfo<Value>& args) { - ProcessWrap* wrap = Unwrap<ProcessWrap>(args.Holder()); + ProcessWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); int signal = args[0]->Int32Value(); int err = uv_process_kill(&wrap->process_, signal); args.GetReturnValue().Set(err); diff --git a/src/signal_wrap.cc b/src/signal_wrap.cc index ec052366f2..3ee0251f9b 100644 --- a/src/signal_wrap.cc +++ b/src/signal_wrap.cc @@ -62,14 +62,16 @@ class SignalWrap : public HandleWrap { } static void Start(const FunctionCallbackInfo<Value>& args) { - SignalWrap* wrap = Unwrap<SignalWrap>(args.Holder()); + SignalWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); int signum = args[0]->Int32Value(); int err = uv_signal_start(&wrap->handle_, OnSignal, signum); args.GetReturnValue().Set(err); } static void Stop(const FunctionCallbackInfo<Value>& args) { - SignalWrap* wrap = Unwrap<SignalWrap>(args.Holder()); + SignalWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); int err = uv_signal_stop(&wrap->handle_); args.GetReturnValue().Set(err); } diff --git a/src/stream_base-inl.h b/src/stream_base-inl.h index e8e73f007e..bdc8211707 100644 --- a/src/stream_base-inl.h +++ b/src/stream_base-inl.h @@ -80,8 +80,9 @@ void StreamBase::GetFD(Local<String> key, Base* handle = Unwrap<Base>(args.Holder()); // Mimic implementation of StreamBase::GetFD() and UDPWrap::GetFD(). - if (handle == nullptr) - return args.GetReturnValue().Set(-1); + ASSIGN_OR_RETURN_UNWRAP(&handle, + args.Holder(), + args.GetReturnValue().Set(UV_EINVAL)); StreamBase* wrap = static_cast<StreamBase*>(handle); if (!wrap->IsAlive()) @@ -97,8 +98,9 @@ void StreamBase::GetBytesRead(Local<String> key, Base* handle = Unwrap<Base>(args.Holder()); // The handle instance hasn't been set. So no bytes could have been read. - if (handle == nullptr) - return args.GetReturnValue().Set(0); + ASSIGN_OR_RETURN_UNWRAP(&handle, + args.Holder(), + args.GetReturnValue().Set(0)); StreamBase* wrap = static_cast<StreamBase*>(handle); // uint64_t -> double. 53bits is enough for all real cases. @@ -111,8 +113,7 @@ void StreamBase::GetExternal(Local<String> key, const PropertyCallbackInfo<Value>& args) { Base* handle = Unwrap<Base>(args.Holder()); - if (handle == nullptr) - return args.GetReturnValue().SetUndefined(); + ASSIGN_OR_RETURN_UNWRAP(&handle, args.Holder()); StreamBase* wrap = static_cast<StreamBase*>(handle); Local<External> ext = External::New(args.GetIsolate(), wrap); @@ -125,8 +126,7 @@ template <class Base, void StreamBase::JSMethod(const FunctionCallbackInfo<Value>& args) { Base* handle = Unwrap<Base>(args.Holder()); - if (handle == nullptr) - return args.GetReturnValue().SetUndefined(); + ASSIGN_OR_RETURN_UNWRAP(&handle, args.Holder()); StreamBase* wrap = static_cast<StreamBase*>(handle); if (!wrap->IsAlive()) diff --git a/src/stream_base.cc b/src/stream_base.cc index 7561a09998..8db127dff6 100644 --- a/src/stream_base.cc +++ b/src/stream_base.cc @@ -329,7 +329,8 @@ int StreamBase::WriteString(const FunctionCallbackInfo<Value>& args) { uv_handle_t* send_handle = nullptr; if (!send_handle_obj.IsEmpty()) { - HandleWrap* wrap = Unwrap<HandleWrap>(send_handle_obj); + HandleWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, send_handle_obj, UV_EINVAL); send_handle = wrap->GetHandle(); // Reference StreamWrap instance to prevent it from being garbage // collected before `AfterWrite` is called. diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc index b942e48078..f3f1d3bfdf 100644 --- a/src/stream_wrap.cc +++ b/src/stream_wrap.cc @@ -170,7 +170,8 @@ static Local<Object> AcceptHandle(Environment* env, StreamWrap* parent) { if (wrap_obj.IsEmpty()) return Local<Object>(); - WrapType* wrap = Unwrap<WrapType>(wrap_obj); + WrapType* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, wrap_obj, Local<Object>()); handle = wrap->UVHandle(); if (uv_accept(parent->stream(), reinterpret_cast<uv_stream_t*>(handle))) @@ -262,7 +263,8 @@ void StreamWrap::OnRead(uv_stream_t* handle, void StreamWrap::SetBlocking(const FunctionCallbackInfo<Value>& args) { - StreamWrap* wrap = Unwrap<StreamWrap>(args.Holder()); + StreamWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); CHECK_GT(args.Length(), 0); if (!wrap->IsAlive()) diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc index 9e95bac0e2..6904b27efd 100644 --- a/src/tcp_wrap.cc +++ b/src/tcp_wrap.cc @@ -164,7 +164,10 @@ TCPWrap::~TCPWrap() { void TCPWrap::SetNoDelay(const FunctionCallbackInfo<Value>& args) { - TCPWrap* wrap = Unwrap<TCPWrap>(args.Holder()); + TCPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); int enable = static_cast<int>(args[0]->BooleanValue()); int err = uv_tcp_nodelay(&wrap->handle_, enable); args.GetReturnValue().Set(err); @@ -172,7 +175,10 @@ void TCPWrap::SetNoDelay(const FunctionCallbackInfo<Value>& args) { void TCPWrap::SetKeepAlive(const FunctionCallbackInfo<Value>& args) { - TCPWrap* wrap = Unwrap<TCPWrap>(args.Holder()); + TCPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); int enable = args[0]->Int32Value(); unsigned int delay = args[1]->Uint32Value(); int err = uv_tcp_keepalive(&wrap->handle_, enable, delay); @@ -182,7 +188,10 @@ void TCPWrap::SetKeepAlive(const FunctionCallbackInfo<Value>& args) { #ifdef _WIN32 void TCPWrap::SetSimultaneousAccepts(const FunctionCallbackInfo<Value>& args) { - TCPWrap* wrap = Unwrap<TCPWrap>(args.Holder()); + TCPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); bool enable = args[0]->BooleanValue(); int err = uv_tcp_simultaneous_accepts(&wrap->handle_, enable); args.GetReturnValue().Set(err); @@ -191,14 +200,20 @@ void TCPWrap::SetSimultaneousAccepts(const FunctionCallbackInfo<Value>& args) { void TCPWrap::Open(const FunctionCallbackInfo<Value>& args) { - TCPWrap* wrap = Unwrap<TCPWrap>(args.Holder()); + TCPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); int fd = static_cast<int>(args[0]->IntegerValue()); uv_tcp_open(&wrap->handle_, fd); } void TCPWrap::Bind(const FunctionCallbackInfo<Value>& args) { - TCPWrap* wrap = Unwrap<TCPWrap>(args.Holder()); + TCPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); node::Utf8Value ip_address(args.GetIsolate(), args[0]); int port = args[1]->Int32Value(); sockaddr_in addr; @@ -213,7 +228,10 @@ void TCPWrap::Bind(const FunctionCallbackInfo<Value>& args) { void TCPWrap::Bind6(const FunctionCallbackInfo<Value>& args) { - TCPWrap* wrap = Unwrap<TCPWrap>(args.Holder()); + TCPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); node::Utf8Value ip6_address(args.GetIsolate(), args[0]); int port = args[1]->Int32Value(); sockaddr_in6 addr; @@ -228,7 +246,10 @@ void TCPWrap::Bind6(const FunctionCallbackInfo<Value>& args) { void TCPWrap::Listen(const FunctionCallbackInfo<Value>& args) { - TCPWrap* wrap = Unwrap<TCPWrap>(args.Holder()); + TCPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); int backlog = args[0]->Int32Value(); int err = uv_listen(reinterpret_cast<uv_stream_t*>(&wrap->handle_), backlog, @@ -261,6 +282,7 @@ void TCPWrap::OnConnection(uv_stream_t* handle, int status) { // Unwrap the client javascript object. TCPWrap* wrap = Unwrap<TCPWrap>(client_obj); + CHECK_NE(wrap, nullptr); uv_stream_t* client_handle = reinterpret_cast<uv_stream_t*>(&wrap->handle_); if (uv_accept(handle, client_handle)) return; @@ -304,7 +326,10 @@ void TCPWrap::AfterConnect(uv_connect_t* req, int status) { void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - TCPWrap* wrap = Unwrap<TCPWrap>(args.Holder()); + TCPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); CHECK(args[0]->IsObject()); CHECK(args[1]->IsString()); @@ -335,7 +360,10 @@ void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) { void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - TCPWrap* wrap = Unwrap<TCPWrap>(args.Holder()); + TCPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); CHECK(args[0]->IsObject()); CHECK(args[1]->IsString()); diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index 779587fe36..20bbce50de 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -54,6 +54,9 @@ TLSWrap::TLSWrap(Environment* env, node::Wrap(object(), this); MakeWeak(this); + // sc comes from an Unwrap. Make sure it was assigned. + CHECK_NE(sc, nullptr); + // We've our own session callbacks SSL_CTX_sess_set_get_cb(sc_->ctx_, SSLWrap<TLSWrap>::GetSessionCallback); SSL_CTX_sess_set_new_cb(sc_->ctx_, SSLWrap<TLSWrap>::NewSessionCallback); @@ -188,7 +191,8 @@ void TLSWrap::Wrap(const FunctionCallbackInfo<Value>& args) { void TLSWrap::Receive(const FunctionCallbackInfo<Value>& args) { - TLSWrap* wrap = Unwrap<TLSWrap>(args.Holder()); + TLSWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); CHECK(Buffer::HasInstance(args[0])); char* data = Buffer::Data(args[0]); @@ -213,7 +217,8 @@ void TLSWrap::Receive(const FunctionCallbackInfo<Value>& args) { void TLSWrap::Start(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - TLSWrap* wrap = Unwrap<TLSWrap>(args.Holder()); + TLSWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); if (wrap->started_) return env->ThrowError("Already started."); @@ -731,7 +736,8 @@ int TLSWrap::DoShutdown(ShutdownWrap* req_wrap) { void TLSWrap::SetVerifyMode(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - TLSWrap* wrap = Unwrap<TLSWrap>(args.Holder()); + TLSWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); if (args.Length() < 2 || !args[0]->IsBoolean() || !args[1]->IsBoolean()) return env->ThrowTypeError("Bad arguments, expected two booleans"); @@ -763,7 +769,8 @@ void TLSWrap::SetVerifyMode(const FunctionCallbackInfo<Value>& args) { void TLSWrap::EnableSessionCallbacks( const FunctionCallbackInfo<Value>& args) { - TLSWrap* wrap = Unwrap<TLSWrap>(args.Holder()); + TLSWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); if (wrap->ssl_ == nullptr) { return wrap->env()->ThrowTypeError( "EnableSessionCallbacks after destroySSL"); @@ -777,7 +784,8 @@ void TLSWrap::EnableSessionCallbacks( void TLSWrap::DestroySSL(const FunctionCallbackInfo<Value>& args) { - TLSWrap* wrap = Unwrap<TLSWrap>(args.Holder()); + TLSWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); // Move all writes to pending wrap->MakePending(); @@ -794,7 +802,8 @@ void TLSWrap::DestroySSL(const FunctionCallbackInfo<Value>& args) { void TLSWrap::EnableCertCb(const FunctionCallbackInfo<Value>& args) { - TLSWrap* wrap = Unwrap<TLSWrap>(args.Holder()); + TLSWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); wrap->WaitForCertCb(OnClientHelloParseEnd, wrap); } @@ -809,7 +818,8 @@ void TLSWrap::OnClientHelloParseEnd(void* arg) { void TLSWrap::GetServername(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - TLSWrap* wrap = Unwrap<TLSWrap>(args.Holder()); + TLSWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); CHECK_NE(wrap->ssl_, nullptr); @@ -826,7 +836,8 @@ void TLSWrap::GetServername(const FunctionCallbackInfo<Value>& args) { void TLSWrap::SetServername(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - TLSWrap* wrap = Unwrap<TLSWrap>(args.Holder()); + TLSWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); if (args.Length() < 1 || !args[0]->IsString()) return env->ThrowTypeError("First argument should be a string"); @@ -875,6 +886,7 @@ int TLSWrap::SelectSNIContextCallback(SSL* s, int* ad, void* arg) { p->sni_context_.Reset(env->isolate(), ctx); SecureContext* sc = Unwrap<SecureContext>(ctx.As<Object>()); + CHECK_NE(sc, nullptr); p->SetSNIContext(sc); return SSL_TLSEXT_ERR_OK; } diff --git a/src/tty_wrap.cc b/src/tty_wrap.cc index 6e91dbcd74..319a74fd36 100644 --- a/src/tty_wrap.cc +++ b/src/tty_wrap.cc @@ -90,7 +90,10 @@ void TTYWrap::IsTTY(const FunctionCallbackInfo<Value>& args) { void TTYWrap::GetWindowSize(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); - TTYWrap* wrap = Unwrap<TTYWrap>(args.Holder()); + TTYWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); CHECK(args[0]->IsArray()); int width, height; @@ -107,7 +110,10 @@ void TTYWrap::GetWindowSize(const FunctionCallbackInfo<Value>& args) { void TTYWrap::SetRawMode(const FunctionCallbackInfo<Value>& args) { - TTYWrap* wrap = Unwrap<TTYWrap>(args.Holder()); + TTYWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); int err = uv_tty_set_mode(&wrap->handle_, args[0]->IsTrue()); args.GetReturnValue().Set(err); } diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index 8c5090ddf7..be141a672c 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -139,7 +139,7 @@ void UDPWrap::New(const FunctionCallbackInfo<Value>& args) { void UDPWrap::GetFD(Local<String>, const PropertyCallbackInfo<Value>& args) { - int fd = -1; + int fd = UV_EBADF; #if !defined(_WIN32) HandleScope scope(args.GetIsolate()); UDPWrap* wrap = Unwrap<UDPWrap>(args.Holder()); @@ -151,7 +151,10 @@ void UDPWrap::GetFD(Local<String>, const PropertyCallbackInfo<Value>& args) { void UDPWrap::DoBind(const FunctionCallbackInfo<Value>& args, int family) { - UDPWrap* wrap = Unwrap<UDPWrap>(args.Holder()); + UDPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); // bind(ip, port, flags) CHECK_EQ(args.Length(), 3); @@ -199,7 +202,7 @@ void UDPWrap::Bind6(const FunctionCallbackInfo<Value>& args) { UDPWrap* wrap = Unwrap<UDPWrap>(args.Holder()); \ CHECK_EQ(args.Length(), 1); \ int flag = args[0]->Int32Value(); \ - int err = fn(&wrap->handle_, flag); \ + int err = wrap == nullptr ? UV_EBADF : fn(&wrap->handle_, flag); \ args.GetReturnValue().Set(err); \ } @@ -213,7 +216,10 @@ X(SetMulticastLoopback, uv_udp_set_multicast_loop) void UDPWrap::SetMembership(const FunctionCallbackInfo<Value>& args, uv_membership membership) { - UDPWrap* wrap = Unwrap<UDPWrap>(args.Holder()); + UDPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); CHECK_EQ(args.Length(), 2); @@ -246,7 +252,10 @@ void UDPWrap::DropMembership(const FunctionCallbackInfo<Value>& args) { void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) { Environment* env = Environment::GetCurrent(args); - UDPWrap* wrap = Unwrap<UDPWrap>(args.Holder()); + UDPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); // send(req, buffer, port, address, hasCallback) CHECK(args[0]->IsObject()); @@ -335,7 +344,10 @@ void UDPWrap::Send6(const FunctionCallbackInfo<Value>& args) { void UDPWrap::RecvStart(const FunctionCallbackInfo<Value>& args) { - UDPWrap* wrap = Unwrap<UDPWrap>(args.Holder()); + UDPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); int err = uv_udp_recv_start(&wrap->handle_, OnAlloc, OnRecv); // UV_EALREADY means that the socket is already bound but that's okay if (err == UV_EALREADY) @@ -345,7 +357,10 @@ void UDPWrap::RecvStart(const FunctionCallbackInfo<Value>& args) { void UDPWrap::RecvStop(const FunctionCallbackInfo<Value>& args) { - UDPWrap* wrap = Unwrap<UDPWrap>(args.Holder()); + UDPWrap* wrap; + ASSIGN_OR_RETURN_UNWRAP(&wrap, + args.Holder(), + args.GetReturnValue().Set(UV_EBADF)); int r = uv_udp_recv_stop(&wrap->handle_); args.GetReturnValue().Set(r); } diff --git a/src/util.h b/src/util.h index dce6c343b1..406f6a1f36 100644 --- a/src/util.h +++ b/src/util.h @@ -8,8 +8,20 @@ #include <stddef.h> #include <stdlib.h> +#ifdef __APPLE__ +#include <tr1/type_traits> +#else +#include <type_traits> // std::remove_reference +#endif + namespace node { +#ifdef __APPLE__ +template <typename T> using remove_reference = std::tr1::remove_reference<T>; +#else +template <typename T> using remove_reference = std::remove_reference<T>; +#endif + #define FIXED_ONE_BYTE_STRING(isolate, string) \ (node::OneByteString((isolate), (string), sizeof(string) - 1)) @@ -53,6 +65,14 @@ namespace node { #define UNREACHABLE() ABORT() +#define ASSIGN_OR_RETURN_UNWRAP(ptr, obj, ...) \ + do { \ + *ptr = \ + Unwrap<typename node::remove_reference<decltype(**ptr)>::type>(obj); \ + if (*ptr == nullptr) \ + return __VA_ARGS__; \ + } while (0) + // TAILQ-style intrusive list node. template <typename T> class ListNode; diff --git a/test/parallel/test-stream-base-no-abort.js b/test/parallel/test-stream-base-no-abort.js new file mode 100644 index 0000000000..d2d8702676 --- /dev/null +++ b/test/parallel/test-stream-base-no-abort.js @@ -0,0 +1,58 @@ +'use strict'; + +const async_wrap = process.binding('async_wrap'); +const uv = process.binding('uv'); +const assert = require('assert'); +const common = require('../common'); +const dgram = require('dgram'); +const fs = require('fs'); +const net = require('net'); +const tls = require('tls'); +const providers = Object.keys(async_wrap.Providers); +var flags = 0; + +// Make sure all asserts have run at least once. +process.on('exit', () => assert.equal(flags, 0b111)); + +function init(id, provider) { + this._external; // Test will abort if nullptr isn't properly checked. + switch (providers[provider]) { + case 'TCPWRAP': + assert.equal(this.fd, uv.UV_EINVAL); + flags |= 0b1; + break; + case 'TLSWRAP': + assert.equal(this.fd, uv.UV_EINVAL); + flags |= 0b10; + break; + case 'UDPWRAP': + assert.equal(this.fd, uv.UV_EBADF); + flags |= 0b100; + break; + } +} + +async_wrap.setupHooks({ init }); +async_wrap.enable(); + +const checkTLS = common.mustCall(function checkTLS() { + const options = { + key: fs.readFileSync(common.fixturesDir + '/keys/ec-key.pem'), + cert: fs.readFileSync(common.fixturesDir + '/keys/ec-cert.pem') + }; + const server = tls.createServer(options, () => {}) + .listen(common.PORT, function() { + tls.connect(common.PORT, { rejectUnauthorized: false }, function() { + this.destroy(); + server.close(); + }); + }); +}); + +const checkTCP = common.mustCall(function checkTCP() { + net.createServer(() => {}).listen(common.PORT, function() { + this.close(checkTLS); + }); +}); + +dgram.createSocket('udp4').close(checkTCP); |