Return error from nghttp2_submit_{headers,request} when self dependency is made

Return NGHTTP2_ERR_INVALID_ARGUMENT from nghttp2_submit_headers() if
given stream ID and pri_spec->stream_id are the same (thus trying to
depend on itself).

Also return NGHTTP2_ERR_INVALID_ARGUMENT from nghttp2_submit_request()
and nghttp2_submit_headers() with stream_id == 1, when new stream ID
equals to pri_spec->stream_id.

Previously, these cases are not checked, and just sent to peer.
This commit is contained in:
Tatsuhiro Tsujikawa 2015-12-25 21:37:18 +09:00
parent dd4d549dc1
commit 8716dd05d4
3 changed files with 41 additions and 1 deletions

View File

@ -3161,6 +3161,9 @@ nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
* :enum:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE` * :enum:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE`
* No stream ID is available because maximum stream ID was * No stream ID is available because maximum stream ID was
* reached. * reached.
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
* Trying to depend on itself (new stream ID equals
* ``pri_spec->stream_id``).
* *
* .. warning:: * .. warning::
* *
@ -3371,7 +3374,8 @@ NGHTTP2_EXTERN int nghttp2_submit_trailer(nghttp2_session *session,
* No stream ID is available because maximum stream ID was * No stream ID is available because maximum stream ID was
* reached. * reached.
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
* The |stream_id| is 0. * The |stream_id| is 0; or trying to depend on itself (stream ID
* equals ``pri_spec->stream_id``).
* :enum:`NGHTTP2_ERR_DATA_EXIST` * :enum:`NGHTTP2_ERR_DATA_EXIST`
* DATA or HEADERS has been already submitted and not fully * DATA or HEADERS has been already submitted and not fully
* processed yet. This happens if stream denoted by |stream_id| * processed yet. This happens if stream denoted by |stream_id|

View File

@ -55,6 +55,16 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags,
goto fail; goto fail;
} }
if (stream_id == -1) {
if ((int32_t)session->next_stream_id == pri_spec->stream_id) {
rv = NGHTTP2_ERR_INVALID_ARGUMENT;
goto fail;
}
} else if (stream_id == pri_spec->stream_id) {
rv = NGHTTP2_ERR_INVALID_ARGUMENT;
goto fail;
}
item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item));
if (item == NULL) { if (item == NULL) {
rv = NGHTTP2_ERR_NOMEM; rv = NGHTTP2_ERR_NOMEM;

View File

@ -3965,6 +3965,7 @@ void test_nghttp2_submit_request_without_data(void) {
nva_out out; nva_out out;
nghttp2_bufs bufs; nghttp2_bufs bufs;
nghttp2_mem *mem; nghttp2_mem *mem;
nghttp2_priority_spec pri_spec;
mem = nghttp2_mem_default(); mem = nghttp2_mem_default();
frame_pack_bufs_init(&bufs); frame_pack_bufs_init(&bufs);
@ -3998,6 +3999,15 @@ void test_nghttp2_submit_request_without_data(void) {
nghttp2_bufs_free(&bufs); nghttp2_bufs_free(&bufs);
nghttp2_hd_inflate_free(&inflater); nghttp2_hd_inflate_free(&inflater);
/* Try to depend on itself is error */
nghttp2_priority_spec_init(&pri_spec, (int32_t)session->next_stream_id, 16,
0);
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
nghttp2_submit_request(session, &pri_spec, reqnv, ARRLEN(reqnv),
NULL, NULL));
nghttp2_session_del(session); nghttp2_session_del(session);
} }
@ -4289,6 +4299,7 @@ void test_nghttp2_submit_headers(void) {
nva_out out; nva_out out;
nghttp2_bufs bufs; nghttp2_bufs bufs;
nghttp2_mem *mem; nghttp2_mem *mem;
nghttp2_priority_spec pri_spec;
mem = nghttp2_mem_default(); mem = nghttp2_mem_default();
frame_pack_bufs_init(&bufs); frame_pack_bufs_init(&bufs);
@ -4343,6 +4354,21 @@ void test_nghttp2_submit_headers(void) {
nghttp2_frame_headers_free(&frame.headers, mem); nghttp2_frame_headers_free(&frame.headers, mem);
nghttp2_hd_inflate_free(&inflater); nghttp2_hd_inflate_free(&inflater);
/* Try to depend on itself */
nghttp2_priority_spec_init(&pri_spec, 3, 16, 0);
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 3, &pri_spec,
reqnv, ARRLEN(reqnv), NULL));
session->next_stream_id = 5;
nghttp2_priority_spec_init(&pri_spec, 5, 16, 0);
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, &pri_spec,
reqnv, ARRLEN(reqnv), NULL));
nghttp2_session_del(session); nghttp2_session_del(session);
} }