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,
|
int nghttp2_session_fail_session(nghttp2_session *session,
|
||||||
nghttp2_error_code error_code)
|
nghttp2_error_code error_code)
|
||||||
{
|
{
|
||||||
|
if(session->goaway_flags & NGHTTP2_GOAWAY_FAIL_ON_SEND) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
session->goaway_flags |= NGHTTP2_GOAWAY_FAIL_ON_SEND;
|
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);
|
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.state = NGHTTP2_RECV_PAYLOAD;
|
||||||
session->iframe.payloadlen =
|
session->iframe.payloadlen =
|
||||||
nghttp2_get_uint16(&session->iframe.headbuf[0]);
|
nghttp2_get_uint16(&session->iframe.headbuf[0]);
|
||||||
if(!nghttp2_frame_is_data_frame(session->iframe.headbuf)) {
|
/* TODO Make payloadlen configurable up to
|
||||||
/* control frame */
|
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;
|
ssize_t buflen = session->iframe.payloadlen;
|
||||||
session->iframe.buflen = buflen;
|
session->iframe.buflen = buflen;
|
||||||
r = nghttp2_reserve_buffer(&session->iframe.buf,
|
r = nghttp2_reserve_buffer(&session->iframe.buf,
|
||||||
|
@ -2901,7 +2922,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(session->iframe.payloadlen == session->iframe.off) {
|
if(session->iframe.payloadlen == session->iframe.off) {
|
||||||
|
if(session->iframe.error_code != NGHTTP2_ERR_FRAME_TOO_LARGE) {
|
||||||
if(!nghttp2_frame_is_data_frame(session->iframe.headbuf)) {
|
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);
|
r = nghttp2_session_process_ctrl_frame(session);
|
||||||
} else {
|
} else {
|
||||||
r = nghttp2_session_process_data_frame(session);
|
r = nghttp2_session_process_data_frame(session);
|
||||||
|
@ -2911,6 +2935,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
||||||
assert(r < NGHTTP2_ERR_FATAL);
|
assert(r < NGHTTP2_ERR_FATAL);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
nghttp2_inbound_frame_reset(&session->iframe);
|
nghttp2_inbound_frame_reset(&session->iframe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,8 @@ int main(int argc, char* argv[])
|
||||||
test_nghttp2_session_recv_eof) ||
|
test_nghttp2_session_recv_eof) ||
|
||||||
!CU_add_test(pSuite, "session_recv_data",
|
!CU_add_test(pSuite, "session_recv_data",
|
||||||
test_nghttp2_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",
|
!CU_add_test(pSuite, "session_add_frame",
|
||||||
test_nghttp2_session_add_frame) ||
|
test_nghttp2_session_add_frame) ||
|
||||||
!CU_add_test(pSuite, "session_on_request_headers_received",
|
!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];
|
size_t wlen = df->feedseq[df->seqidx] > len ? len : df->feedseq[df->seqidx];
|
||||||
memcpy(data, df->datamark, wlen);
|
memcpy(data, df->datamark, wlen);
|
||||||
df->datamark += wlen;
|
df->datamark += wlen;
|
||||||
if(wlen <= len) {
|
|
||||||
++df->seqidx;
|
|
||||||
} else {
|
|
||||||
df->feedseq[df->seqidx] -= wlen;
|
df->feedseq[df->seqidx] -= wlen;
|
||||||
|
if(df->feedseq[df->seqidx] == 0) {
|
||||||
|
++df->seqidx;
|
||||||
}
|
}
|
||||||
return wlen;
|
return wlen;
|
||||||
}
|
}
|
||||||
|
@ -282,6 +281,62 @@ static const char *null_val_nv[] = { "Version", "HTTP/1.1",
|
||||||
"Foo", NULL,
|
"Foo", NULL,
|
||||||
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)
|
void test_nghttp2_session_recv(void)
|
||||||
{
|
{
|
||||||
nghttp2_session *session;
|
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_invalid_frame(void);
|
||||||
void test_nghttp2_session_recv_eof(void);
|
void test_nghttp2_session_recv_eof(void);
|
||||||
void test_nghttp2_session_recv_data(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_add_frame(void);
|
||||||
void test_nghttp2_session_on_request_headers_received(void);
|
void test_nghttp2_session_on_request_headers_received(void);
|
||||||
void test_nghttp2_session_on_response_headers_received(void);
|
void test_nghttp2_session_on_response_headers_received(void);
|
||||||
|
|
Loading…
Reference in New Issue