Repository navigation
fix(ext/node): emit ERR_HTTP2_TOO_MANY_INVALID_FRAMES for empty DATA frames without END_STREAM - #33644
Conversation
β¦frames without END_STREAM Enables tests/node_compat/runner/suite/test/parallel/test-http2-empty-frame-without-eof.js Co-authored-by: Divy Srivastava <me@littledivy.com>
4a179e5 to
d845e89
Compare
fibibot
left a comment
There was a problem hiding this comment.
LGTM. Walked through the substance:
-
Empty DATA frame detection in
on_frame_recv_callback: whenframe_header_length(frame) == 0andEND_STREAMis unset, incrementinvalid_frame_countand trip if it exceedsmax_invalid_frames. nghttp2 itself doesn't flag empty-DATA-without-EOF as a protocol error, so the JS layer needs to count it β same as Node'sHandleDataFrameinsrc/node_http2.cc. -
Post-increment comparison corrected in
on_invalid_frame_recv_callback: changed fromcount >= session.max_invalid_frames(with a> 0guard that disabledmax=0) tocount > session.max_invalid_frames, matching Node'sif (invalid_frame_count_++ > max_invalid_frames). The semantics now line up exactly:max=0: 1 invalid frame allowed (count=0, check 0 > 0 false), 2nd trips (count=1, 1 > 0 true).max=2: 2 allowed, 3rd trips.- That's exactly what the upstream test exercises (max=0 β must error with "Too many invalid HTTP/2 frames"; max=2 β must not error).
-
custom_recv_error_codeplumbing: nghttp2 callbacks setSome("ERR_HTTP2_TOO_MANY_INVALID_FRAMES"), thenreceive_datachecks the return value ofnghttp2_session_mem_recvβ if negative (fatal),emit_session_internal_error(ret)builds a v8 scope and invokessession_internal_error_cb(integerCode, customErrorCode). Mirrors Node'sHttp2Session::custom_recv_error_code_exactly. β -
emit_session_internal_erroruses the same v8-scope pattern (from_raw_isolate_ptrβContextScopeβ callback.call) as the existinginvoke_session_internal_errorhelper. The custom code istake()n out of the field so subsequent emits don't re-emit it. Note this has 2 args (errno, customErrorCode) where the existinginvoke_session_internal_errorhas 1 (errnoonly) β that's intentional, since this is the path that needs to surface the custom code to JS. -
JS-side
kCustomErrorMessagesmap translatesERR_HTTP2_TOO_MANY_INVALID_FRAMESto"Too many invalid HTTP/2 frames".__proto__: nullprevents pollution. Falls back to the code string if unknown. Matches the test'sexpectsError({code: 'ERR_HTTP2_TOO_MANY_INVALID_FRAMES', message: 'Too many invalid HTTP/2 frames'}). β -
saturating_addoninvalid_frame_count: u32defends against overflow at the cost of saturating atu32::MAX. Reasonable β by the time you've received 4B invalid frames, the session is well past the limit.
Test enrollment alphabetically positioned (dont-override < empty-frame-without-eof < endafterheaders). β
CI fully green: 133 SUCCESS, 0 FAILURE, 2 SKIPPED. All 36 test node_compat shards Γ all 12 test unit_node shards Γ all 24 test specs shards green.
Summary
Enables
test-http2-empty-frame-without-eofin node_compat suite.Test plan
cargo test --test node_compat -- test-http2-empty-frame-without-eof