Connection error if payload size is strictly greater than (1 << 14) - 1
It would be desired to add option to make this limit configurable. Fix scripted_recv_callback in tests.
This commit is contained in:
parent
1f3b96e233
commit
b37f99ca03
|
@ -83,7 +83,13 @@ static int32_t nghttp2_pushed_stream_pri(nghttp2_stream *stream)
|
|||
int nghttp2_session_fail_session(nghttp2_session *session,
|
||||
nghttp2_error_code error_code)
|
||||
{
|
||||
if(session->goaway_flags & NGHTTP2_GOAWAY_FAIL_ON_SEND) {
|
||||
return 0;
|
||||
}
|
||||
session->goaway_flags |= NGHTTP2_GOAWAY_FAIL_ON_SEND;
|
||||
if(session->goaway_flags & NGHTTP2_GOAWAY_SEND) {
|
||||
return 0;
|
||||
}
|
||||
return nghttp2_submit_goaway(session, error_code, NULL, 0);
|
||||
}
|
||||
|
||||
|
@ -2806,8 +2812,23 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
session->iframe.state = NGHTTP2_RECV_PAYLOAD;
|
||||
session->iframe.payloadlen =
|
||||
nghttp2_get_uint16(&session->iframe.headbuf[0]);
|
||||
if(!nghttp2_frame_is_data_frame(session->iframe.headbuf)) {
|
||||
/* control frame */
|
||||
/* TODO Make payloadlen configurable up to
|
||||
NGHTTP2_MAX_FRAME_LENGTH */
|
||||
if(session->iframe.payloadlen > NGHTTP2_MAX_HTTP_FRAME_LENGTH) {
|
||||
session->iframe.error_code = NGHTTP2_ERR_FRAME_TOO_LARGE;
|
||||
session->iframe.state = NGHTTP2_RECV_PAYLOAD_IGN;
|
||||
/* Make inflater fail forcibly to disallow reception of
|
||||
further HEADERS or PUSH_PROMISE */
|
||||
session->hd_inflater.bad = 1;
|
||||
/* Just tear down session for now */
|
||||
r = nghttp2_session_fail_session(session, NGHTTP2_FRAME_TOO_LARGE);
|
||||
if(r != 0) {
|
||||
/* FATAL */
|
||||
assert(r < NGHTTP2_ERR_FATAL);
|
||||
return r;
|
||||
}
|
||||
} else if(!nghttp2_frame_is_data_frame(session->iframe.headbuf)) {
|
||||
/* non-DATA frame */
|
||||
ssize_t buflen = session->iframe.payloadlen;
|
||||
session->iframe.buflen = buflen;
|
||||
r = nghttp2_reserve_buffer(&session->iframe.buf,
|
||||
|
@ -2901,15 +2922,19 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
}
|
||||
}
|
||||
if(session->iframe.payloadlen == session->iframe.off) {
|
||||
if(!nghttp2_frame_is_data_frame(session->iframe.headbuf)) {
|
||||
r = nghttp2_session_process_ctrl_frame(session);
|
||||
} else {
|
||||
r = nghttp2_session_process_data_frame(session);
|
||||
}
|
||||
if(r < 0) {
|
||||
/* FATAL */
|
||||
assert(r < NGHTTP2_ERR_FATAL);
|
||||
return r;
|
||||
if(session->iframe.error_code != NGHTTP2_ERR_FRAME_TOO_LARGE) {
|
||||
if(!nghttp2_frame_is_data_frame(session->iframe.headbuf)) {
|
||||
/* TODO Introduce callback which is invoked when payload is
|
||||
ignored, especially for frame too large */
|
||||
r = nghttp2_session_process_ctrl_frame(session);
|
||||
} else {
|
||||
r = nghttp2_session_process_data_frame(session);
|
||||
}
|
||||
if(r < 0) {
|
||||
/* FATAL */
|
||||
assert(r < NGHTTP2_ERR_FATAL);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
nghttp2_inbound_frame_reset(&session->iframe);
|
||||
}
|
||||
|
|
|
@ -84,6 +84,8 @@ int main(int argc, char* argv[])
|
|||
test_nghttp2_session_recv_eof) ||
|
||||
!CU_add_test(pSuite, "session_recv_data",
|
||||
test_nghttp2_session_recv_data) ||
|
||||
!CU_add_test(pSuite, "session_recv_frame_too_large",
|
||||
test_nghttp2_session_recv_frame_too_large) ||
|
||||
!CU_add_test(pSuite, "session_add_frame",
|
||||
test_nghttp2_session_add_frame) ||
|
||||
!CU_add_test(pSuite, "session_on_request_headers_received",
|
||||
|
|
|
@ -101,10 +101,9 @@ static ssize_t scripted_recv_callback(nghttp2_session *session,
|
|||
size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx];
|
||||
memcpy(data, df->datamark, wlen);
|
||||
df->datamark += wlen;
|
||||
if(wlen <= len) {
|
||||
df->feedseq[df->seqidx] -= wlen;
|
||||
if(df->feedseq[df->seqidx] == 0) {
|
||||
++df->seqidx;
|
||||
} else {
|
||||
df->feedseq[df->seqidx] -= wlen;
|
||||
}
|
||||
return wlen;
|
||||
}
|
||||
|
@ -282,6 +281,62 @@ static const char *null_val_nv[] = { "Version", "HTTP/1.1",
|
|||
"Foo", NULL,
|
||||
NULL };
|
||||
|
||||
void test_nghttp2_session_recv_frame_too_large(void)
|
||||
{
|
||||
nghttp2_session *session;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
scripted_data_feed df;
|
||||
my_user_data user_data;
|
||||
uint8_t data[NGHTTP2_FRAME_HEAD_LENGTH + NGHTTP2_MAX_HTTP_FRAME_LENGTH + 1];
|
||||
nghttp2_frame_hd hd;
|
||||
nghttp2_outbound_item *item;
|
||||
nghttp2_frame frame;
|
||||
uint8_t *framebuf = NULL;
|
||||
size_t framebuflen = 0;
|
||||
size_t framelen;
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.send_callback = null_send_callback;
|
||||
callbacks.recv_callback = scripted_recv_callback;
|
||||
callbacks.on_frame_recv_callback = on_frame_recv_callback;
|
||||
user_data.df = &df;
|
||||
|
||||
nghttp2_session_client_new(&session, &callbacks, &user_data);
|
||||
|
||||
nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_NONE,
|
||||
NGHTTP2_PRI_DEFAULT, NGHTTP2_STREAM_OPENED,
|
||||
NULL);
|
||||
memset(data, 0, sizeof(data));
|
||||
hd.length = NGHTTP2_MAX_HTTP_FRAME_LENGTH + 1;
|
||||
hd.type = NGHTTP2_DATA;
|
||||
hd.flags = NGHTTP2_FLAG_END_STREAM;
|
||||
hd.stream_id = 1;
|
||||
nghttp2_frame_pack_frame_hd(data, &hd);
|
||||
scripted_data_feed_init(&df, data, sizeof(data));
|
||||
|
||||
CU_ASSERT(0 == nghttp2_session_recv(session));
|
||||
|
||||
item = nghttp2_session_get_next_ob_item(session);
|
||||
CU_ASSERT(item != NULL);
|
||||
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
|
||||
CU_ASSERT(NGHTTP2_FRAME_TOO_LARGE == OB_CTRL(item)->goaway.error_code);
|
||||
|
||||
/* Check next frame can be received */
|
||||
nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
|
||||
framelen = nghttp2_frame_pack_ping(&framebuf, &framebuflen, &frame.ping);
|
||||
nghttp2_frame_ping_free(&frame.ping);
|
||||
|
||||
scripted_data_feed_init(&df, framebuf, framelen);
|
||||
|
||||
user_data.frame_recv_cb_called = 0;
|
||||
CU_ASSERT(0 == nghttp2_session_recv(session));
|
||||
|
||||
CU_ASSERT(1 == user_data.frame_recv_cb_called);
|
||||
|
||||
free(framebuf);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_session_recv(void)
|
||||
{
|
||||
nghttp2_session *session;
|
||||
|
|
|
@ -30,6 +30,7 @@ void test_nghttp2_session_recv_invalid_stream_id(void);
|
|||
void test_nghttp2_session_recv_invalid_frame(void);
|
||||
void test_nghttp2_session_recv_eof(void);
|
||||
void test_nghttp2_session_recv_data(void);
|
||||
void test_nghttp2_session_recv_frame_too_large(void);
|
||||
void test_nghttp2_session_add_frame(void);
|
||||
void test_nghttp2_session_on_request_headers_received(void);
|
||||
void test_nghttp2_session_on_response_headers_received(void);
|
||||
|
|
Loading…
Reference in New Issue