37
37
namespace node {
38
38
39
39
using v8::Array;
40
+ using v8::ArrayBuffer;
40
41
using v8::ArrayBufferView;
42
+ using v8::BackingStore;
41
43
using v8::Context;
42
44
using v8::DontDelete;
43
- using v8::EscapableHandleScope;
44
45
using v8::Exception;
45
46
using v8::False;
46
47
using v8::Function;
@@ -313,6 +314,16 @@ inline bool Set(
313
314
OneByteString (env->isolate (), value))
314
315
.IsNothing ();
315
316
}
317
+
318
+ std::string GetBIOError () {
319
+ BIO* bio = BIO_new (BIO_s_mem ());
320
+ CHECK_NOT_NULL (bio);
321
+ auto cleanup = OnScopeLeave ([&]() { BIO_free_all (bio); });
322
+ ERR_print_errors (bio);
323
+ BUF_MEM* mem;
324
+ BIO_get_mem_ptr (bio, &mem);
325
+ return std::string (mem->data , mem->length );
326
+ }
316
327
} // namespace
317
328
318
329
TLSWrap::TLSWrap (Environment* env,
@@ -572,7 +583,8 @@ void TLSWrap::EncOut() {
572
583
// No encrypted output ready to write to the underlying stream.
573
584
if (BIO_pending (enc_out_) == 0 ) {
574
585
Debug (this , " No pending encrypted output" );
575
- if (pending_cleartext_input_.size () == 0 ) {
586
+ if (!pending_cleartext_input_ ||
587
+ pending_cleartext_input_->ByteLength () == 0 ) {
576
588
if (!in_dowrite_) {
577
589
Debug (this , " No pending cleartext input, not inside DoWrite()" );
578
590
InvokeQueued (0 );
@@ -665,84 +677,9 @@ void TLSWrap::OnStreamAfterWrite(WriteWrap* req_wrap, int status) {
665
677
EncOut ();
666
678
}
667
679
668
- MaybeLocal<Value> TLSWrap::GetSSLError (int status, int * err, std::string* msg) {
669
- EscapableHandleScope scope (env ()->isolate ());
670
-
671
- // ssl_ is already destroyed in reading EOF by close notify alert.
672
- if (ssl_ == nullptr )
673
- return MaybeLocal<Value>();
674
-
675
- *err = SSL_get_error (ssl_.get (), status);
676
- switch (*err) {
677
- case SSL_ERROR_NONE:
678
- case SSL_ERROR_WANT_READ:
679
- case SSL_ERROR_WANT_WRITE:
680
- case SSL_ERROR_WANT_X509_LOOKUP:
681
- return MaybeLocal<Value>();
682
-
683
- case SSL_ERROR_ZERO_RETURN:
684
- return scope.Escape (env ()->zero_return_string ());
685
-
686
- case SSL_ERROR_SSL:
687
- case SSL_ERROR_SYSCALL:
688
- {
689
- unsigned long ssl_err = ERR_peek_error (); // NOLINT(runtime/int)
690
- BIO* bio = BIO_new (BIO_s_mem ());
691
- ERR_print_errors (bio);
692
-
693
- BUF_MEM* mem;
694
- BIO_get_mem_ptr (bio, &mem);
695
-
696
- Isolate* isolate = env ()->isolate ();
697
- Local<Context> context = isolate->GetCurrentContext ();
698
-
699
- Local<String> message = OneByteString (isolate, mem->data , mem->length );
700
- Local<Value> exception = Exception::Error (message);
701
- Local<Object> obj =
702
- exception->ToObject (context).FromMaybe (Local<Object>());
703
- if (UNLIKELY (obj.IsEmpty ()))
704
- return MaybeLocal<Value>();
705
-
706
- const char * ls = ERR_lib_error_string (ssl_err);
707
- const char * fs = ERR_func_error_string (ssl_err);
708
- const char * rs = ERR_reason_error_string (ssl_err);
709
-
710
- if (!Set (env (), obj, env ()->library_string (), ls) ||
711
- !Set (env (), obj, env ()->function_string (), fs)) {
712
- return MaybeLocal<Value>();
713
- }
714
-
715
- if (rs != nullptr ) {
716
- if (!Set (env (), obj, env ()->reason_string (), rs))
717
- return MaybeLocal<Value>();
718
-
719
- // SSL has no API to recover the error name from the number, so we
720
- // transform reason strings like "this error" to "ERR_SSL_THIS_ERROR",
721
- // which ends up being close to the original error macro name.
722
- std::string code (rs);
723
-
724
- for (auto & c : code)
725
- c = (c == ' ' ) ? ' _' : ToUpper (c);
726
-
727
- if (!Set (env (), obj,
728
- env ()->code_string (),
729
- (" ERR_SSL_" + code).c_str ())) {
730
- return MaybeLocal<Value>();
731
- }
732
- }
733
-
734
- if (msg != nullptr )
735
- msg->assign (mem->data , mem->data + mem->length );
736
-
737
- BIO_free_all (bio);
738
-
739
- return scope.Escape (exception);
740
- }
741
-
742
- default :
743
- UNREACHABLE ();
744
- }
745
- UNREACHABLE ();
680
+ int TLSWrap::GetSSLError (int status) const {
681
+ // ssl_ might already be destroyed for reading EOF from a close notify alert.
682
+ return ssl_ != nullptr ? SSL_get_error (ssl_.get (), status) : 0 ;
746
683
}
747
684
748
685
void TLSWrap::ClearOut () {
@@ -809,24 +746,61 @@ void TLSWrap::ClearOut() {
809
746
// See node#1642 and SSL_read(3SSL) for details.
810
747
if (read <= 0 ) {
811
748
HandleScope handle_scope (env ()->isolate ());
812
- int err;
749
+ Local<Value> exception;
750
+ int err = GetSSLError (read);
751
+ switch (err) {
752
+ case SSL_ERROR_ZERO_RETURN:
753
+ // Ignore ZERO_RETURN after EOF, it is basically not an error.
754
+ if (eof_) return ;
755
+ exception = env ()->zero_return_string ();
756
+ break ;
813
757
814
- Local<Value> arg = GetSSLError (read, &err, nullptr )
815
- .FromMaybe (Local<Value>());
758
+ case SSL_ERROR_SSL:
759
+ case SSL_ERROR_SYSCALL:
760
+ {
761
+ unsigned long ssl_err = ERR_peek_error (); // NOLINT(runtime/int)
762
+
763
+ Local<Context> context = env ()->isolate ()->GetCurrentContext ();
764
+ if (UNLIKELY (context.IsEmpty ())) return ;
765
+ const std::string error_str = GetBIOError ();
766
+ Local<String> message = OneByteString (env ()->isolate (),
767
+ error_str.c_str (),
768
+ error_str.size ());
769
+ if (UNLIKELY (message.IsEmpty ())) return ;
770
+ exception = Exception::Error (message);
771
+ if (UNLIKELY (exception.IsEmpty ())) return ;
772
+ Local<Object> obj;
773
+ if (UNLIKELY (!exception->ToObject (context).ToLocal (&obj))) return ;
774
+
775
+ const char * ls = ERR_lib_error_string (ssl_err);
776
+ const char * fs = ERR_func_error_string (ssl_err);
777
+ const char * rs = ERR_reason_error_string (ssl_err);
778
+ if (!Set (env (), obj, env ()->library_string (), ls) ||
779
+ !Set (env (), obj, env ()->function_string (), fs) ||
780
+ !Set (env (), obj, env ()->reason_string (), rs, false )) return ;
781
+ // SSL has no API to recover the error name from the number, so we
782
+ // transform reason strings like "this error" to "ERR_SSL_THIS_ERROR",
783
+ // which ends up being close to the original error macro name.
784
+ std::string code (rs);
785
+ // TODO(RaisinTen): Pass an appropriate execution policy when it is
786
+ // implemented in our supported compilers.
787
+ std::transform (code.begin (), code.end (), code.begin (),
788
+ [](char c) { return c == ' ' ? ' _' : ToUpper (c); });
789
+ if (!Set (env (), obj,
790
+ env ()->code_string (), (" ERR_SSL_" + code).c_str ())) return ;
791
+ }
792
+ break ;
816
793
817
- // Ignore ZERO_RETURN after EOF, it is basically not a error
818
- if (err == SSL_ERROR_ZERO_RETURN && eof_)
819
- return ;
794
+ default : return ;
795
+ }
820
796
821
- if (LIKELY (!arg.IsEmpty ())) {
822
- Debug (this , " Got SSL error (%d), calling onerror" , err);
823
- // When TLS Alert are stored in wbio,
824
- // it should be flushed to socket before destroyed.
825
- if (BIO_pending (enc_out_) != 0 )
826
- EncOut ();
797
+ Debug (this , " Got SSL error (%d), calling onerror" , err);
798
+ // When TLS Alert are stored in wbio,
799
+ // it should be flushed to socket before destroyed.
800
+ if (BIO_pending (enc_out_) != 0 )
801
+ EncOut ();
827
802
828
- MakeCallback (env ()->onerror_string (), 1 , &arg);
829
- }
803
+ MakeCallback (env ()->onerror_string (), 1 , &exception);
830
804
}
831
805
}
832
806
@@ -843,18 +817,19 @@ void TLSWrap::ClearIn() {
843
817
return ;
844
818
}
845
819
846
- if (pending_cleartext_input_.size () == 0 ) {
820
+ if (!pending_cleartext_input_ ||
821
+ pending_cleartext_input_->ByteLength () == 0 ) {
847
822
Debug (this , " Returning from ClearIn(), no pending data" );
848
823
return ;
849
824
}
850
825
851
- AllocatedBuffer data = std::move (pending_cleartext_input_);
826
+ std::unique_ptr<BackingStore> bs = std::move (pending_cleartext_input_);
852
827
MarkPopErrorOnReturn mark_pop_error_on_return;
853
828
854
- NodeBIO::FromBIO (enc_out_)->set_allocate_tls_hint (data. size ());
855
- int written = SSL_write (ssl_.get (), data. data (), data. size ());
856
- Debug (this , " Writing %zu bytes, written = %d" , data. size (), written);
857
- CHECK (written == -1 || written == static_cast <int >(data. size ()));
829
+ NodeBIO::FromBIO (enc_out_)->set_allocate_tls_hint (bs-> ByteLength ());
830
+ int written = SSL_write (ssl_.get (), bs-> Data (), bs-> ByteLength ());
831
+ Debug (this , " Writing %zu bytes, written = %d" , bs-> ByteLength (), written);
832
+ CHECK (written == -1 || written == static_cast <int >(bs-> ByteLength ()));
858
833
859
834
// All written
860
835
if (written != -1 ) {
@@ -863,24 +838,20 @@ void TLSWrap::ClearIn() {
863
838
}
864
839
865
840
// Error or partial write
866
- HandleScope handle_scope (env ()->isolate ());
867
- Context::Scope context_scope (env ()->context ());
868
-
869
- int err;
870
- std::string error_str;
871
- MaybeLocal<Value> arg = GetSSLError (written, &err, &error_str);
872
- if (!arg.IsEmpty ()) {
841
+ int err = GetSSLError (written);
842
+ if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
873
843
Debug (this , " Got SSL error (%d)" , err);
874
844
write_callback_scheduled_ = true ;
875
845
// TODO(@sam-github) Should forward an error object with
876
846
// .code/.function/.etc, if possible.
877
- return InvokeQueued (UV_EPROTO, error_str.c_str ());
847
+ InvokeQueued (UV_EPROTO, GetBIOError ().c_str ());
848
+ return ;
878
849
}
879
850
880
851
Debug (this , " Pushing data back" );
881
852
// Push back the not-yet-written data. This can be skipped in the error
882
853
// case because no further writes would succeed anyway.
883
- pending_cleartext_input_ = std::move (data );
854
+ pending_cleartext_input_ = std::move (bs );
884
855
}
885
856
886
857
std::string TLSWrap::diagnostic_name () const {
@@ -998,7 +969,7 @@ int TLSWrap::DoWrite(WriteWrap* w,
998
969
return 0 ;
999
970
}
1000
971
1001
- AllocatedBuffer data ;
972
+ std::unique_ptr<BackingStore> bs ;
1002
973
MarkPopErrorOnReturn mark_pop_error_on_return;
1003
974
1004
975
int written = 0 ;
@@ -1012,36 +983,39 @@ int TLSWrap::DoWrite(WriteWrap* w,
1012
983
// and copying it when it could just be used.
1013
984
1014
985
if (nonempty_count != 1 ) {
1015
- data = AllocatedBuffer::AllocateManaged (env (), length);
986
+ {
987
+ NoArrayBufferZeroFillScope no_zero_fill_scope (env ()->isolate_data ());
988
+ bs = ArrayBuffer::NewBackingStore (env ()->isolate (), length);
989
+ }
1016
990
size_t offset = 0 ;
1017
991
for (i = 0 ; i < count; i++) {
1018
- memcpy (data.data () + offset, bufs[i].base , bufs[i].len );
992
+ memcpy (static_cast <char *>(bs->Data ()) + offset,
993
+ bufs[i].base , bufs[i].len );
1019
994
offset += bufs[i].len ;
1020
995
}
1021
996
1022
997
NodeBIO::FromBIO (enc_out_)->set_allocate_tls_hint (length);
1023
- written = SSL_write (ssl_.get (), data. data (), length);
998
+ written = SSL_write (ssl_.get (), bs-> Data (), length);
1024
999
} else {
1025
1000
// Only one buffer: try to write directly, only store if it fails
1026
1001
uv_buf_t * buf = &bufs[nonempty_i];
1027
1002
NodeBIO::FromBIO (enc_out_)->set_allocate_tls_hint (buf->len );
1028
1003
written = SSL_write (ssl_.get (), buf->base , buf->len );
1029
1004
1030
1005
if (written == -1 ) {
1031
- data = AllocatedBuffer::AllocateManaged (env (), length);
1032
- memcpy (data.data (), buf->base , buf->len );
1006
+ NoArrayBufferZeroFillScope no_zero_fill_scope (env ()->isolate_data ());
1007
+ bs = ArrayBuffer::NewBackingStore (env ()->isolate (), length);
1008
+ memcpy (bs->Data (), buf->base , buf->len );
1033
1009
}
1034
1010
}
1035
1011
1036
1012
CHECK (written == -1 || written == static_cast <int >(length));
1037
1013
Debug (this , " Writing %zu bytes, written = %d" , length, written);
1038
1014
1039
1015
if (written == -1 ) {
1040
- int err;
1041
- MaybeLocal<Value> arg = GetSSLError (written, &err, &error_);
1042
-
1043
1016
// If we stopped writing because of an error, it's fatal, discard the data.
1044
- if (!arg.IsEmpty ()) {
1017
+ int err = GetSSLError (written);
1018
+ if (err == SSL_ERROR_SSL || err == SSL_ERROR_SYSCALL) {
1045
1019
// TODO(@jasnell): What are we doing with the error?
1046
1020
Debug (this , " Got SSL error (%d), returning UV_EPROTO" , err);
1047
1021
current_write_.reset ();
@@ -1050,8 +1024,9 @@ int TLSWrap::DoWrite(WriteWrap* w,
1050
1024
1051
1025
Debug (this , " Saving data for later write" );
1052
1026
// Otherwise, save unwritten data so it can be written later by ClearIn().
1053
- CHECK_EQ (pending_cleartext_input_.size (), 0 );
1054
- pending_cleartext_input_ = std::move (data);
1027
+ CHECK (!pending_cleartext_input_ ||
1028
+ pending_cleartext_input_->ByteLength () == 0 );
1029
+ pending_cleartext_input_ = std::move (bs);
1055
1030
}
1056
1031
1057
1032
// Write any encrypted/handshake output that may be ready.
@@ -1492,8 +1467,9 @@ void TLSWrap::MemoryInfo(MemoryTracker* tracker) const {
1492
1467
tracker->TrackField (" sni_context" , sni_context_);
1493
1468
tracker->TrackField (" error" , error_);
1494
1469
tracker->TrackFieldWithSize (" pending_cleartext_input" ,
1495
- pending_cleartext_input_.size (),
1496
- " AllocatedBuffer" );
1470
+ pending_cleartext_input_ ?
1471
+ pending_cleartext_input_->ByteLength () : 0 ,
1472
+ " std::unique_ptr<v8::BackingStore>" );
1497
1473
if (enc_in_ != nullptr )
1498
1474
tracker->TrackField (" enc_in" , NodeBIO::FromBIO (enc_in_));
1499
1475
if (enc_out_ != nullptr )
0 commit comments