Commit 2ca7b51e authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

Fix the incoming last empty header value is not checked properly

This change fixes the bug that spdylay_frame_unpack_nv does not check
the size of header value if it is the last value in NULL separated
list.
parent ce58af0c
...@@ -185,6 +185,7 @@ int spdylay_frame_unpack_nv(char ***nv_ptr, spdylay_buffer *in, ...@@ -185,6 +185,7 @@ int spdylay_frame_unpack_nv(char ***nv_ptr, spdylay_buffer *in,
uint32_t len; uint32_t len;
char *name, *val; char *name, *val;
char *stop; char *stop;
int multival;
len = spdylay_frame_get_nv_len(&reader, len_size); len = spdylay_frame_get_nv_len(&reader, len_size);
if(len == 0) { if(len == 0) {
invalid_header_block = 1; invalid_header_block = 1;
...@@ -204,6 +205,7 @@ int spdylay_frame_unpack_nv(char ***nv_ptr, spdylay_buffer *in, ...@@ -204,6 +205,7 @@ int spdylay_frame_unpack_nv(char ***nv_ptr, spdylay_buffer *in,
val = data; val = data;
spdylay_buffer_reader_data(&reader, (uint8_t*)data, len); spdylay_buffer_reader_data(&reader, (uint8_t*)data, len);
multival = 0;
for(stop = data+len; data != stop; ++data) { for(stop = data+len; data != stop; ++data) {
if(*data == '\0') { if(*data == '\0') {
*idx++ = name; *idx++ = name;
...@@ -212,9 +214,15 @@ int spdylay_frame_unpack_nv(char ***nv_ptr, spdylay_buffer *in, ...@@ -212,9 +214,15 @@ int spdylay_frame_unpack_nv(char ***nv_ptr, spdylay_buffer *in,
invalid_header_block = 1; invalid_header_block = 1;
} }
val = data+1; val = data+1;
multival = 1;
} }
} }
*data = '\0'; *data = '\0';
/* Check last header value is empty if NULL separator was
found. */
if(multival && val == data) {
invalid_header_block = 1;
}
++data; ++data;
*idx++ = name; *idx++ = name;
......
...@@ -216,6 +216,10 @@ int main(int argc, char* argv[]) ...@@ -216,6 +216,10 @@ int main(int argc, char* argv[])
test_spdylay_frame_unpack_nv_check_name_spdy2) || test_spdylay_frame_unpack_nv_check_name_spdy2) ||
!CU_add_test(pSuite, "frame_unpack_nv_check_name_spdy3", !CU_add_test(pSuite, "frame_unpack_nv_check_name_spdy3",
test_spdylay_frame_unpack_nv_check_name_spdy3) || test_spdylay_frame_unpack_nv_check_name_spdy3) ||
!CU_add_test(pSuite, "frame_unpack_nv_last_empty_value_spdy2",
test_spdylay_frame_unpack_nv_last_empty_value_spdy2) ||
!CU_add_test(pSuite, "frame_unpack_nv_last_empty_value_spdy3",
test_spdylay_frame_unpack_nv_last_empty_value_spdy3) ||
!CU_add_test(pSuite, "frame_nv_set_origin", !CU_add_test(pSuite, "frame_nv_set_origin",
test_spdylay_frame_nv_set_origin) || test_spdylay_frame_nv_set_origin) ||
!CU_add_test(pSuite, "stream_add_pushed_stream", !CU_add_test(pSuite, "stream_add_pushed_stream",
......
...@@ -707,6 +707,8 @@ void test_spdylay_frame_nv_3to2(void) ...@@ -707,6 +707,8 @@ void test_spdylay_frame_nv_3to2(void)
spdylay_frame_nv_del(nv); spdylay_frame_nv_del(nv);
} }
/* This function intentionally does not merge same header field into
one */
static size_t spdylay_pack_nv(uint8_t *buf, size_t buflen, const char **nv, static size_t spdylay_pack_nv(uint8_t *buf, size_t buflen, const char **nv,
size_t len_size) size_t len_size)
{ {
...@@ -790,6 +792,51 @@ void test_spdylay_frame_unpack_nv_check_name_spdy3(void) ...@@ -790,6 +792,51 @@ void test_spdylay_frame_unpack_nv_check_name_spdy3(void)
(spdylay_frame_get_len_size(SPDYLAY_PROTO_SPDY3)); (spdylay_frame_get_len_size(SPDYLAY_PROTO_SPDY3));
} }
static void test_spdylay_frame_unpack_nv_last_empty_value_with(size_t len_size)
{
size_t nvbuflen;
uint8_t nvbuf[256];
uint8_t *nvbufptr;
spdylay_buffer buffer;
char **outnv = 0;
const char hdname[] = "method";
nvbufptr = nvbuf;
spdylay_frame_put_nv_len(nvbufptr, 1, len_size);
nvbufptr += len_size;
spdylay_frame_put_nv_len(nvbufptr, sizeof(hdname)-1, len_size);
nvbufptr += len_size;
memcpy(nvbufptr, hdname, sizeof(hdname)-1);
nvbufptr += sizeof(hdname)-1;
spdylay_frame_put_nv_len(nvbufptr, 4, len_size);
nvbufptr += len_size;
/* Copy including terminating NULL */
memcpy(nvbufptr, "GET", 4);
nvbufptr += 4;
nvbuflen = nvbufptr - nvbuf;
spdylay_buffer_init(&buffer, 32);
spdylay_buffer_write(&buffer, nvbuf, nvbuflen);
CU_ASSERT(SPDYLAY_ERR_INVALID_HEADER_BLOCK ==
spdylay_frame_unpack_nv(&outnv, &buffer, len_size));
spdylay_frame_nv_del(outnv);
spdylay_buffer_free(&buffer);
}
void test_spdylay_frame_unpack_nv_last_empty_value_spdy2(void)
{
test_spdylay_frame_unpack_nv_last_empty_value_with
(spdylay_frame_get_len_size(SPDYLAY_PROTO_SPDY2));
}
void test_spdylay_frame_unpack_nv_last_empty_value_spdy3(void)
{
test_spdylay_frame_unpack_nv_last_empty_value_with
(spdylay_frame_get_len_size(SPDYLAY_PROTO_SPDY3));
}
void test_spdylay_frame_nv_set_origin(void) void test_spdylay_frame_nv_set_origin(void)
{ {
spdylay_origin origin; spdylay_origin origin;
......
...@@ -50,6 +50,8 @@ void test_spdylay_frame_nv_2to3(void); ...@@ -50,6 +50,8 @@ void test_spdylay_frame_nv_2to3(void);
void test_spdylay_frame_nv_3to2(void); void test_spdylay_frame_nv_3to2(void);
void test_spdylay_frame_unpack_nv_check_name_spdy2(void); void test_spdylay_frame_unpack_nv_check_name_spdy2(void);
void test_spdylay_frame_unpack_nv_check_name_spdy3(void); void test_spdylay_frame_unpack_nv_check_name_spdy3(void);
void test_spdylay_frame_unpack_nv_last_empty_value_spdy2(void);
void test_spdylay_frame_unpack_nv_last_empty_value_spdy3(void);
void test_spdylay_frame_nv_set_origin(void); void test_spdylay_frame_nv_set_origin(void);
#endif /* SPDYLAY_FRAME_TEST_H */ #endif /* SPDYLAY_FRAME_TEST_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment