From 77b15549e9f9e3fa54aca413eb79ac75786db121 Mon Sep 17 00:00:00 2001 From: Denys Otrishko Date: Mon, 18 Nov 2019 19:07:33 +0200 Subject: [PATCH 1/6] http2: replace direct array usage with struct for js_fields_ --- src/node_http2.cc | 16 +++++++++------- src/node_http2.h | 18 +++++++++++++----- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/node_http2.cc b/src/node_http2.cc index 7170907ced1b3e..4c1e5dd5831b81 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -647,7 +647,9 @@ Http2Session::Http2Session(Environment* env, { // Make the js_fields_ property accessible to JS land. Local ab = - ArrayBuffer::New(env->isolate(), js_fields_, kSessionUint8FieldCount); + ArrayBuffer::New(env->isolate(), + reinterpret_cast(&js_fields_), + kSessionUint8FieldCount); Local uint8_arr = Uint8Array::New(ab, 0, kSessionUint8FieldCount); USE(wrap->Set(env->context(), env->fields_string(), uint8_arr)); @@ -1046,7 +1048,7 @@ int Http2Session::OnFrameNotSent(nghttp2_session* handle, if (error_code == NGHTTP2_ERR_SESSION_CLOSING || error_code == NGHTTP2_ERR_STREAM_CLOSED || error_code == NGHTTP2_ERR_STREAM_CLOSING || - session->js_fields_[kSessionFrameErrorListenerCount] == 0) { + session->js_fields_.frame_error_listener_count == 0) { return 0; } @@ -1349,7 +1351,7 @@ void Http2Session::HandleHeadersFrame(const nghttp2_frame* frame) { // are considered advisory only, so this has no real effect other than to // simply let user code know that the priority has changed. void Http2Session::HandlePriorityFrame(const nghttp2_frame* frame) { - if (js_fields_[kSessionPriorityListenerCount] == 0) return; + if (js_fields_.priority_listener_count == 0) return; Isolate* isolate = env()->isolate(); HandleScope scope(isolate); Local context = env()->context(); @@ -1418,7 +1420,7 @@ void Http2Session::HandleGoawayFrame(const nghttp2_frame* frame) { // Called by OnFrameReceived when a complete ALTSVC frame has been received. void Http2Session::HandleAltSvcFrame(const nghttp2_frame* frame) { - if (!(js_fields_[kBitfield] & (1 << kSessionHasAltsvcListeners))) return; + if (!(js_fields_.bitfield & (1 << kSessionHasAltsvcListeners))) return; Isolate* isolate = env()->isolate(); HandleScope scope(isolate); Local context = env()->context(); @@ -1497,7 +1499,7 @@ void Http2Session::HandlePingFrame(const nghttp2_frame* frame) { return; } - if (!(js_fields_[kBitfield] & (1 << kSessionHasPingListeners))) return; + if (!(js_fields_.bitfield & (1 << kSessionHasPingListeners))) return; // Notify the session that a ping occurred arg = Buffer::Copy(env(), reinterpret_cast(frame->ping.opaque_data), @@ -1509,8 +1511,8 @@ void Http2Session::HandlePingFrame(const nghttp2_frame* frame) { void Http2Session::HandleSettingsFrame(const nghttp2_frame* frame) { bool ack = frame->hd.flags & NGHTTP2_FLAG_ACK; if (!ack) { - js_fields_[kBitfield] &= ~(1 << kSessionRemoteSettingsIsUpToDate); - if (!(js_fields_[kBitfield] & (1 << kSessionHasRemoteSettingsListeners))) + js_fields_.bitfield &= ~(1 << kSessionRemoteSettingsIsUpToDate); + if (!(js_fields_.bitfield & (1 << kSessionHasRemoteSettingsListeners))) return; // This is not a SETTINGS acknowledgement, notify and return MakeCallback(env()->http2session_on_settings_function(), 0, nullptr); diff --git a/src/node_http2.h b/src/node_http2.h index 1444738470f9c7..61092b60c0cb6e 100644 --- a/src/node_http2.h +++ b/src/node_http2.h @@ -673,15 +673,23 @@ class Http2Stream::Provider::Stream : public Http2Stream::Provider { void* user_data); }; +typedef struct { + uint8_t bitfield; + uint8_t priority_listener_count; + uint8_t frame_error_listener_count; +} SessionJSFields; + // Indices for js_fields_, which serves as a way to communicate data with JS // land fast. In particular, we store information about the number/presence // of certain event listeners in JS, and skip calls from C++ into JS if they // are missing. enum SessionUint8Fields { - kBitfield, // See below - kSessionPriorityListenerCount, - kSessionFrameErrorListenerCount, - kSessionUint8FieldCount + kBitfield = offsetof(SessionJSFields, bitfield), // See below + kSessionPriorityListenerCount = + offsetof(SessionJSFields, priority_listener_count), + kSessionFrameErrorListenerCount = + offsetof(SessionJSFields, frame_error_listener_count), + kSessionUint8FieldCount = sizeof(SessionJSFields) }; enum SessionBitfieldFlags { @@ -968,7 +976,7 @@ class Http2Session : public AsyncWrap, public StreamListener { nghttp2_session* session_; // JS-accessible numeric fields, as indexed by SessionUint8Fields. - uint8_t js_fields_[kSessionUint8FieldCount] = {}; + SessionJSFields js_fields_ = {}; // The session type: client or server nghttp2_session_type session_type_; From 25df704299382de2af959a083f68b976733e712f Mon Sep 17 00:00:00 2001 From: Denys Otrishko Date: Mon, 18 Nov 2019 21:44:21 +0200 Subject: [PATCH 2/6] http2: allow to configure maximum tolerated invalid frames --- doc/api/http2.md | 12 +++ lib/internal/http2/core.js | 16 +++- src/node_http2.cc | 9 +- src/node_http2.h | 4 +- .../test-http2-createsecureserver-options.js | 31 ++++++- .../test-http2-createserver-options.js | 31 ++++++- .../parallel/test-http2-max-invalid-frames.js | 86 +++++++++++++++++++ 7 files changed, 181 insertions(+), 8 deletions(-) create mode 100644 test/parallel/test-http2-max-invalid-frames.js diff --git a/doc/api/http2.md b/doc/api/http2.md index 53461ac58d4605..82132b3ec5157f 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -1941,6 +1941,9 @@ error will be thrown.