tls: use after free in tls_wrap · nodejs/node@743f890
@@ -298,10 +298,12 @@ void TLSWrap::EncOut() {
298298299299300300void TLSWrap::OnStreamAfterWrite(WriteWrap* req_wrap, int status) {
301-// Report back to the previous listener as well. This is only needed for the
302-// "empty" writes that are passed through directly to the underlying stream.
303-if (req_wrap != nullptr)
304- previous_listener_->OnStreamAfterWrite(req_wrap, status);
301+if (current_empty_write_ != nullptr) {
302+ WriteWrap* finishing = current_empty_write_;
303+ current_empty_write_ = nullptr;
304+ finishing->Done(status);
305+return;
306+ }
305307306308if (ssl_ == nullptr)
307309 status = UV_ECANCELED;
@@ -567,18 +569,17 @@ int TLSWrap::DoWrite(WriteWrap* w,
567569// However, if there is any data that should be written to the socket,
568570// the callback should not be invoked immediately
569571if (BIO_pending(enc_out_) == 0) {
570-// We destroy the current WriteWrap* object and create a new one that
571-// matches the underlying stream, rather than the TLSWrap itself.
572-573-// Note: We cannot simply use w->object() because of the "optimized"
574-// way in which we read persistent handles; the JS object itself might be
575-// destroyed by w->Dispose(), and the Local<Object> we have is not a
576-// "real" handle in the sense the V8 is aware of its existence.
577- Local<Object> req_wrap_obj =
578- w->GetAsyncWrap()->persistent().Get(env()->isolate());
579- w->Dispose();
580- w = underlying_stream()->CreateWriteWrap(req_wrap_obj);
581-return stream_->DoWrite(w, bufs, count, send_handle);
572+CHECK_EQ(current_empty_write_, nullptr);
573+ current_empty_write_ = w;
574+ StreamWriteResult res =
575+underlying_stream()->Write(bufs, count, send_handle);
576+if (!res.async) {
577+env()->SetImmediate([](Environment* env, void* data) {
578+ TLSWrap* self = static_cast<TLSWrap*>(data);
579+ self->OnStreamAfterWrite(self->current_empty_write_, 0);
580+ }, this, object());
581+ }
582+return 0;
582583 }
583584 }
584585