@@ -3263,7 +3263,9 @@ static int session_call_on_invalid_header(nghttp2_session *session,
32633263 session , frame , nv -> name -> base , nv -> name -> len , nv -> value -> base ,
32643264 nv -> value -> len , nv -> flags , session -> user_data );
32653265 } else {
3266- return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE ;
3266+ /* If both callbacks are not set, the invalid field nv is
3267+ ignored. */
3268+ return 0 ;
32673269 }
32683270
32693271 if (rv == NGHTTP2_ERR_PAUSE || rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE ) {
@@ -3348,6 +3350,10 @@ static uint32_t get_error_code_from_lib_error_code(int lib_error_code) {
33483350 case NGHTTP2_ERR_HTTP_HEADER :
33493351 case NGHTTP2_ERR_HTTP_MESSAGING :
33503352 return NGHTTP2_PROTOCOL_ERROR ;
3353+ case NGHTTP2_ERR_INTERNAL :
3354+ return NGHTTP2_INTERNAL_ERROR ;
3355+ case NGHTTP2_ERR_PUSH_CANCEL :
3356+ return NGHTTP2_CANCEL ;
33513357 default :
33523358 return NGHTTP2_INTERNAL_ERROR ;
33533359 }
@@ -3384,7 +3390,7 @@ static int session_handle_invalid_stream2(nghttp2_session *session,
33843390 if (rv != 0 ) {
33853391 return rv ;
33863392 }
3387- if (session -> callbacks .on_invalid_frame_recv_callback ) {
3393+ if (frame && session -> callbacks .on_invalid_frame_recv_callback ) {
33883394 if (session -> callbacks .on_invalid_frame_recv_callback (
33893395 session , frame , lib_error_code , session -> user_data ) != 0 ) {
33903396 return NGHTTP2_ERR_CALLBACK_FAILURE ;
@@ -3539,7 +3545,29 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
35393545
35403546 rv2 = session_call_on_invalid_header (session , frame , & nv );
35413547 if (rv2 == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE ) {
3542- rv = NGHTTP2_ERR_HTTP_HEADER ;
3548+ DEBUGF ("recv: HTTP error: type=%u, id=%d, header %.*s: %.*s\n" ,
3549+ frame -> hd .type , frame -> hd .stream_id , (int )nv .name -> len ,
3550+ nv .name -> base , (int )nv .value -> len , nv .value -> base );
3551+
3552+ rv = session_call_error_callback (
3553+ session , NGHTTP2_ERR_HTTP_HEADER ,
3554+ "Invalid HTTP header field was received: frame type: "
3555+ "%u, stream: %d, name: [%.*s], value: [%.*s]" ,
3556+ frame -> hd .type , frame -> hd .stream_id , (int )nv .name -> len ,
3557+ nv .name -> base , (int )nv .value -> len , nv .value -> base );
3558+
3559+ if (nghttp2_is_fatal (rv )) {
3560+ return rv ;
3561+ }
3562+
3563+ rv = session_handle_invalid_stream2 (
3564+ session , subject_stream -> stream_id , frame ,
3565+ NGHTTP2_ERR_HTTP_HEADER );
3566+ if (nghttp2_is_fatal (rv )) {
3567+ return rv ;
3568+ }
3569+
3570+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE ;
35433571 } else {
35443572 if (rv2 != 0 ) {
35453573 return rv2 ;
@@ -3579,13 +3607,8 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
35793607 return rv ;
35803608 }
35813609
3582- rv =
3583- session_handle_invalid_stream2 (session , subject_stream -> stream_id ,
3584- frame , NGHTTP2_ERR_HTTP_HEADER );
3585- if (nghttp2_is_fatal (rv )) {
3586- return rv ;
3587- }
3588- return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE ;
3610+ return nghttp2_session_terminate_session (session ,
3611+ NGHTTP2_PROTOCOL_ERROR );
35893612 }
35903613 }
35913614 if (rv == 0 ) {
@@ -3698,27 +3721,7 @@ static int session_after_header_block_received(nghttp2_session *session) {
36983721 }
36993722 }
37003723 if (rv != 0 ) {
3701- int32_t stream_id ;
3702-
3703- if (frame -> hd .type == NGHTTP2_PUSH_PROMISE ) {
3704- stream_id = frame -> push_promise .promised_stream_id ;
3705- } else {
3706- stream_id = frame -> hd .stream_id ;
3707- }
3708-
3709- rv = session_handle_invalid_stream2 (session , stream_id , frame ,
3710- NGHTTP2_ERR_HTTP_MESSAGING );
3711- if (nghttp2_is_fatal (rv )) {
3712- return rv ;
3713- }
3714-
3715- if (frame -> hd .type == NGHTTP2_HEADERS &&
3716- (frame -> hd .flags & NGHTTP2_FLAG_END_STREAM )) {
3717- nghttp2_stream_shutdown (stream , NGHTTP2_SHUT_RD );
3718- /* Don't call nghttp2_session_close_stream_if_shut_rdwr
3719- because RST_STREAM has been submitted. */
3720- }
3721- return 0 ;
3724+ return nghttp2_session_terminate_session (session , NGHTTP2_PROTOCOL_ERROR );
37223725 }
37233726 }
37243727
@@ -4054,8 +4057,7 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) {
40544057 rv = nghttp2_stream_update_remote_initial_window_size (
40554058 stream , arg -> new_window_size , arg -> old_window_size );
40564059 if (rv != 0 ) {
4057- return nghttp2_session_add_rst_stream (arg -> session , stream -> stream_id ,
4058- NGHTTP2_FLOW_CONTROL_ERROR );
4060+ return NGHTTP2_ERR_FLOW_CONTROL ;
40594061 }
40604062
40614063 /* If window size gets positive, push deferred DATA frame to
@@ -4081,6 +4083,8 @@ static int update_remote_initial_window_size_func(void *entry, void *ptr) {
40814083 *
40824084 * NGHTTP2_ERR_NOMEM
40834085 * Out of memory.
4086+ * NGHTTP2_ERR_FLOW_CONTROL
4087+ * Window size gets out of range.
40844088 */
40854089static int
40864090session_update_remote_initial_window_size (nghttp2_session * session ,
@@ -4104,8 +4108,7 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) {
41044108 rv = nghttp2_stream_update_local_initial_window_size (
41054109 stream , arg -> new_window_size , arg -> old_window_size );
41064110 if (rv != 0 ) {
4107- return nghttp2_session_add_rst_stream (arg -> session , stream -> stream_id ,
4108- NGHTTP2_FLOW_CONTROL_ERROR );
4111+ return NGHTTP2_ERR_FLOW_CONTROL ;
41094112 }
41104113
41114114 if (stream -> window_update_queued ) {
@@ -4139,6 +4142,8 @@ static int update_local_initial_window_size_func(void *entry, void *ptr) {
41394142 *
41404143 * NGHTTP2_ERR_NOMEM
41414144 * Out of memory.
4145+ * NGHTTP2_ERR_FLOW_CONTROL
4146+ * Window size gets out of range.
41424147 */
41434148static int
41444149session_update_local_initial_window_size (nghttp2_session * session ,
@@ -4525,9 +4530,9 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session,
45254530 session -> max_incoming_reserved_streams ) {
45264531 /* Currently, client does not retain closed stream, so we don't
45274532 check NGHTTP2_SHUT_RD condition here. */
4528-
4529- rv = nghttp2_session_add_rst_stream (
4530- session , frame -> push_promise . promised_stream_id , NGHTTP2_CANCEL );
4533+ rv = session_handle_invalid_stream2 ( session ,
4534+ frame -> push_promise . promised_stream_id ,
4535+ NULL , NGHTTP2_ERR_PUSH_CANCEL );
45314536 if (rv != 0 ) {
45324537 return rv ;
45334538 }
@@ -4684,8 +4689,9 @@ static int session_on_stream_window_update_received(nghttp2_session *session,
46844689 }
46854690 if (NGHTTP2_MAX_WINDOW_SIZE - frame -> window_update .window_size_increment <
46864691 stream -> remote_window_size ) {
4687- return session_handle_invalid_stream (session , frame ,
4688- NGHTTP2_ERR_FLOW_CONTROL );
4692+ return session_handle_invalid_connection (
4693+ session , frame , NGHTTP2_ERR_FLOW_CONTROL ,
4694+ "WINDOW_UPDATE: window size overflow" );
46894695 }
46904696 stream -> remote_window_size += frame -> window_update .window_size_increment ;
46914697
@@ -4915,16 +4921,7 @@ int nghttp2_session_on_data_received(nghttp2_session *session,
49154921 if (session_enforce_http_messaging (session ) &&
49164922 (frame -> hd .flags & NGHTTP2_FLAG_END_STREAM )) {
49174923 if (nghttp2_http_on_remote_end_stream (stream ) != 0 ) {
4918- rv = nghttp2_session_add_rst_stream (session , stream -> stream_id ,
4919- NGHTTP2_PROTOCOL_ERROR );
4920- if (nghttp2_is_fatal (rv )) {
4921- return rv ;
4922- }
4923-
4924- nghttp2_stream_shutdown (stream , NGHTTP2_SHUT_RD );
4925- /* Don't call nghttp2_session_close_stream_if_shut_rdwr because
4926- RST_STREAM has been submitted. */
4927- return 0 ;
4924+ return nghttp2_session_terminate_session (session , NGHTTP2_PROTOCOL_ERROR );
49284925 }
49294926 }
49304927
@@ -4982,8 +4979,8 @@ int nghttp2_session_update_recv_stream_window_size(nghttp2_session *session,
49824979 rv = adjust_recv_window_size (& stream -> recv_window_size , delta_size ,
49834980 stream -> local_window_size );
49844981 if (rv != 0 ) {
4985- return nghttp2_session_add_rst_stream (session , stream -> stream_id ,
4986- NGHTTP2_FLOW_CONTROL_ERROR );
4982+ return nghttp2_session_terminate_session (session ,
4983+ NGHTTP2_FLOW_CONTROL_ERROR );
49874984 }
49884985 /* We don't have to send WINDOW_UPDATE if the data received is the
49894986 last chunk in the incoming stream. */
@@ -5542,8 +5539,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
55425539 }
55435540
55445541 if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE ) {
5545- rv = nghttp2_session_add_rst_stream (
5546- session , iframe -> frame .hd .stream_id , NGHTTP2_INTERNAL_ERROR );
5542+ rv = session_handle_invalid_stream2 (
5543+ session , iframe -> frame .hd .stream_id , NULL , NGHTTP2_ERR_INTERNAL );
55475544 if (nghttp2_is_fatal (rv )) {
55485545 return rv ;
55495546 }
@@ -5956,8 +5953,8 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
59565953 }
59575954
59585955 if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE ) {
5959- rv = nghttp2_session_add_rst_stream (
5960- session , iframe -> frame .hd .stream_id , NGHTTP2_INTERNAL_ERROR );
5956+ rv = session_handle_invalid_stream2 (
5957+ session , iframe -> frame .hd .stream_id , NULL , NGHTTP2_ERR_INTERNAL );
59615958 if (nghttp2_is_fatal (rv )) {
59625959 return rv ;
59635960 }
@@ -6031,9 +6028,9 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
60316028 }
60326029
60336030 if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE ) {
6034- rv = nghttp2_session_add_rst_stream (
6035- session , iframe -> frame .push_promise .promised_stream_id ,
6036- NGHTTP2_INTERNAL_ERROR );
6031+ rv = session_handle_invalid_stream2 (
6032+ session , iframe -> frame .push_promise .promised_stream_id , NULL ,
6033+ NGHTTP2_ERR_INTERNAL );
60376034 if (nghttp2_is_fatal (rv )) {
60386035 return rv ;
60396036 }
@@ -6211,12 +6208,12 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
62116208 iframe -> payloadleft -= hd_proclen ;
62126209
62136210 /* Use promised stream ID for PUSH_PROMISE */
6214- rv = nghttp2_session_add_rst_stream (
6211+ rv = session_handle_invalid_stream2 (
62156212 session ,
62166213 iframe -> frame .hd .type == NGHTTP2_PUSH_PROMISE
62176214 ? iframe -> frame .push_promise .promised_stream_id
62186215 : iframe -> frame .hd .stream_id ,
6219- NGHTTP2_INTERNAL_ERROR );
6216+ NULL , NGHTTP2_ERR_INTERNAL );
62206217 if (nghttp2_is_fatal (rv )) {
62216218 return rv ;
62226219 }
@@ -6263,6 +6260,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
62636260 if (nghttp2_is_fatal (rv )) {
62646261 return rv ;
62656262 }
6263+
6264+ if (iframe -> state == NGHTTP2_IB_IGN_ALL ) {
6265+ return (nghttp2_ssize )inlen ;
6266+ }
62666267 }
62676268 session_inbound_frame_reset (session );
62686269
@@ -6488,6 +6489,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
64886489 if (nghttp2_is_fatal (rv )) {
64896490 return rv ;
64906491 }
6492+
6493+ if (iframe -> state == NGHTTP2_IB_IGN_ALL ) {
6494+ return (nghttp2_ssize )inlen ;
6495+ }
64916496 }
64926497
64936498 busy = 1 ;
@@ -6546,6 +6551,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
65466551 return rv ;
65476552 }
65486553
6554+ if (iframe -> state == NGHTTP2_IB_IGN_ALL ) {
6555+ return (nghttp2_ssize )inlen ;
6556+ }
6557+
65496558 data_readlen =
65506559 inbound_frame_effective_readlen (iframe , iframe -> payloadleft , readlen );
65516560
@@ -6575,28 +6584,13 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
65756584 if (data_readlen > 0 ) {
65766585 if (session_enforce_http_messaging (session )) {
65776586 if (nghttp2_http_on_data_chunk (stream , (size_t )data_readlen ) != 0 ) {
6578- if (session -> opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE ) {
6579- /* Consume all data for connection immediately here */
6580- rv = session_update_connection_consumed_size (
6581- session , (size_t )data_readlen );
6582-
6583- if (nghttp2_is_fatal (rv )) {
6584- return rv ;
6585- }
6586-
6587- if (iframe -> state == NGHTTP2_IB_IGN_DATA ) {
6588- return (nghttp2_ssize )inlen ;
6589- }
6590- }
6591-
6592- rv = nghttp2_session_add_rst_stream (
6593- session , iframe -> frame .hd .stream_id , NGHTTP2_PROTOCOL_ERROR );
6587+ rv = nghttp2_session_terminate_session (session ,
6588+ NGHTTP2_PROTOCOL_ERROR );
65946589 if (nghttp2_is_fatal (rv )) {
65956590 return rv ;
65966591 }
6597- busy = 1 ;
6598- iframe -> state = NGHTTP2_IB_IGN_DATA ;
6599- break ;
6592+
6593+ return (nghttp2_ssize )inlen ;
66006594 }
66016595 }
66026596 if (session -> callbacks .on_data_chunk_recv_callback ) {
@@ -6623,6 +6617,10 @@ nghttp2_ssize nghttp2_session_mem_recv2(nghttp2_session *session,
66236617 return rv ;
66246618 }
66256619
6620+ if (iframe -> state == NGHTTP2_IB_IGN_ALL ) {
6621+ return (nghttp2_ssize )inlen ;
6622+ }
6623+
66266624 session_inbound_frame_reset (session );
66276625
66286626 break ;
0 commit comments