diff --git a/lib/includes/spdylay/spdylay.h b/lib/includes/spdylay/spdylay.h index 556a314..c2f1494 100644 --- a/lib/includes/spdylay/spdylay.h +++ b/lib/includes/spdylay/spdylay.h @@ -1653,7 +1653,8 @@ const char* spdylay_strerror(int error_code); * negative error codes: * * :enum:`SPDYLAY_ERR_INVALID_ARGUMENT` - * The |pri| is invalid. + * The |pri| is invalid; or the |nv| includes empty name or NULL + * value. * :enum:`SPDYLAY_ERR_NOMEM` * Out of memory. */ @@ -1697,6 +1698,8 @@ int spdylay_submit_request(spdylay_session *session, uint8_t pri, * This function returns 0 if it succeeds, or one of the following * negative error codes: * + * :enum:`SPDYLAY_ERR_INVALID_ARGUMENT` + * The |nv| includes empty name or NULL value. * :enum:`SPDYLAY_ERR_NOMEM` * Out of memory. */ @@ -1744,7 +1747,7 @@ int spdylay_submit_response(spdylay_session *session, * * :enum:`SPDYLAY_ERR_INVALID_ARGUMENT` * The |pri| is invalid; or the Associated-To-Stream-ID is - * invalid. + * invalid; or the |nv| includes empty name or NULL value. * :enum:`SPDYLAY_ERR_NOMEM` * Out of memory. */ @@ -1778,6 +1781,8 @@ int spdylay_submit_syn_stream(spdylay_session *session, uint8_t flags, * This function returns 0 if it succeeds, or one of the following * negative error codes: * + * :enum:`SPDYLAY_ERR_INVALID_ARGUMENT` + * The |nv| includes empty name or NULL value. * :enum:`SPDYLAY_ERR_NOMEM` * Out of memory. */ @@ -1810,6 +1815,8 @@ int spdylay_submit_syn_reply(spdylay_session *session, uint8_t flags, * This function returns 0 if it succeeds, or one of the following * negative error codes: * + * :enum:`SPDYLAY_ERR_INVALID_ARGUMENT` + * The |nv| includes empty name or NULL value. * :enum:`SPDYLAY_ERR_NOMEM` * Out of memory. */ diff --git a/lib/spdylay_frame.c b/lib/spdylay_frame.c index f7acaba..dd1897e 100644 --- a/lib/spdylay_frame.c +++ b/lib/spdylay_frame.c @@ -1267,3 +1267,14 @@ ssize_t spdylay_frame_nv_offset(spdylay_frame_type type, uint16_t version) } return -1; } + +int spdylay_frame_nv_check_null(const char **nv) +{ + size_t i; + for(i = 0; nv[i]; i += 2) { + if(nv[i][0] == '\0' || nv[i+1] == NULL) { + return 0; + } + } + return 1; +} diff --git a/lib/spdylay_frame.h b/lib/spdylay_frame.h index 4d52e2a..a5a481e 100644 --- a/lib/spdylay_frame.h +++ b/lib/spdylay_frame.h @@ -783,4 +783,11 @@ void spdylay_frame_iv_sort(spdylay_settings_entry *iv, size_t niv); */ ssize_t spdylay_frame_nv_offset(spdylay_frame_type type, uint16_t version); +/* + * Checks names are not empty string and values are not NULL. + * + * This function returns nonzero if it succeeds, or 0. + */ +int spdylay_frame_nv_check_null(const char **nv); + #endif /* SPDYLAY_FRAME_H */ diff --git a/lib/spdylay_submit.c b/lib/spdylay_submit.c index 488205a..5cfcf75 100644 --- a/lib/spdylay_submit.c +++ b/lib/spdylay_submit.c @@ -55,6 +55,9 @@ static int spdylay_submit_syn_stream_shared return SPDYLAY_ERR_INVALID_ARGUMENT; } } + if(!spdylay_frame_nv_check_null(nv)) { + return SPDYLAY_ERR_INVALID_ARGUMENT; + } if(data_prd != NULL && data_prd->read_callback != NULL) { data_prd_copy = malloc(sizeof(spdylay_data_provider)); if(data_prd_copy == NULL) { @@ -119,6 +122,9 @@ int spdylay_submit_syn_reply(spdylay_session *session, uint8_t flags, spdylay_frame *frame; char **nv_copy; uint8_t flags_copy; + if(!spdylay_frame_nv_check_null(nv)) { + return SPDYLAY_ERR_INVALID_ARGUMENT; + } frame = malloc(sizeof(spdylay_frame)); if(frame == NULL) { return SPDYLAY_ERR_NOMEM; @@ -149,6 +155,9 @@ int spdylay_submit_headers(spdylay_session *session, uint8_t flags, spdylay_frame *frame; char **nv_copy; uint8_t flags_copy; + if(!spdylay_frame_nv_check_null(nv)) { + return SPDYLAY_ERR_INVALID_ARGUMENT; + } frame = malloc(sizeof(spdylay_frame)); if(frame == NULL) { return SPDYLAY_ERR_NOMEM; @@ -270,6 +279,9 @@ int spdylay_submit_response(spdylay_session *session, char **nv_copy; uint8_t flags = 0; spdylay_data_provider *data_prd_copy = NULL; + if(!spdylay_frame_nv_check_null(nv)) { + return SPDYLAY_ERR_INVALID_ARGUMENT; + } if(data_prd != NULL && data_prd->read_callback != NULL) { data_prd_copy = malloc(sizeof(spdylay_data_provider)); if(data_prd_copy == NULL) { diff --git a/tests/main.c b/tests/main.c index 049c1de..9aa2270 100644 --- a/tests/main.c +++ b/tests/main.c @@ -100,6 +100,8 @@ int main(int argc, char* argv[]) test_spdylay_submit_syn_stream) || !CU_add_test(pSuite, "submit_syn_reply", test_spdylay_submit_syn_reply) || !CU_add_test(pSuite, "submit_headers", test_spdylay_submit_headers) || + !CU_add_test(pSuite, "submit_invalid_nv", + test_spdylay_submit_invalid_nv) || !CU_add_test(pSuite, "session_reply_fail", test_spdylay_session_reply_fail) || !CU_add_test(pSuite, "session_on_headers_received", diff --git a/tests/spdylay_session_test.c b/tests/spdylay_session_test.c index 5c34ae1..880c80e 100644 --- a/tests/spdylay_session_test.c +++ b/tests/spdylay_session_test.c @@ -249,6 +249,14 @@ static spdylay_settings_entry* dup_iv(const spdylay_settings_entry *iv, return spdylay_frame_iv_copy(iv, niv); } +static const char *empty_name_nv[] = { "Version", "HTTP/1.1", + "", "empty name", + NULL }; + +static const char *null_val_nv[] = { "Version", "HTTP/1.1", + "Foo", NULL, + NULL }; + void test_spdylay_session_recv(void) { spdylay_session *session; @@ -1065,6 +1073,60 @@ void test_spdylay_submit_headers(void) spdylay_session_del(session); } +void test_spdylay_submit_invalid_nv(void) +{ + spdylay_session *session; + spdylay_session_callbacks callbacks; + + memset(&callbacks, 0, sizeof(spdylay_session_callbacks)); + + CU_ASSERT(0 == spdylay_session_client_new(&session, SPDYLAY_PROTO_SPDY3, + &callbacks, NULL)); + + /* spdylay_submit_request */ + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_submit_request(session, 3, empty_name_nv, NULL, NULL)); + + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_submit_request(session, 3, null_val_nv, NULL, NULL)); + + /* spdylay_submit_response */ + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_submit_response(session, 2, empty_name_nv, NULL)); + + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_submit_response(session, 2, null_val_nv, NULL)); + + /* spdylay_submit_syn_stream */ + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_submit_syn_stream(session, SPDYLAY_CTRL_FLAG_NONE, 0, + 0, empty_name_nv, NULL)); + + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_submit_syn_stream(session, SPDYLAY_CTRL_FLAG_NONE, 0, + 0, null_val_nv, NULL)); + + /* spdylay_submit_syn_reply */ + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_submit_syn_reply(session, SPDYLAY_CTRL_FLAG_NONE, 2, + empty_name_nv)); + + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_submit_syn_reply(session, SPDYLAY_CTRL_FLAG_NONE, 2, + null_val_nv)); + + /* spdylay_submit_headers */ + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_submit_headers(session, SPDYLAY_CTRL_FLAG_NONE, 2, + empty_name_nv)); + + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_submit_headers(session, SPDYLAY_CTRL_FLAG_NONE, 2, + null_val_nv)); + + spdylay_session_del(session); +} + void test_spdylay_session_reply_fail(void) { spdylay_session *session; diff --git a/tests/spdylay_session_test.h b/tests/spdylay_session_test.h index ce777bf..78c0962 100644 --- a/tests/spdylay_session_test.h +++ b/tests/spdylay_session_test.h @@ -41,6 +41,7 @@ void test_spdylay_submit_request_with_null_data_read_callback(void); void test_spdylay_submit_syn_stream(void); void test_spdylay_submit_syn_reply(void); void test_spdylay_submit_headers(void); +void test_spdylay_submit_invalid_nv(void); void test_spdylay_session_reply_fail(void); void test_spdylay_session_on_headers_received(void); void test_spdylay_session_on_ping_received(void);