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.
This commit is contained in:
Tatsuhiro Tsujikawa 2013-03-23 18:11:21 +09:00
parent ce58af0c8c
commit 2ca7b51eb6
4 changed files with 61 additions and 0 deletions

View File

@ -185,6 +185,7 @@ int spdylay_frame_unpack_nv(char ***nv_ptr, spdylay_buffer *in,
uint32_t len;
char *name, *val;
char *stop;
int multival;
len = spdylay_frame_get_nv_len(&reader, len_size);
if(len == 0) {
invalid_header_block = 1;
@ -204,6 +205,7 @@ int spdylay_frame_unpack_nv(char ***nv_ptr, spdylay_buffer *in,
val = data;
spdylay_buffer_reader_data(&reader, (uint8_t*)data, len);
multival = 0;
for(stop = data+len; data != stop; ++data) {
if(*data == '\0') {
*idx++ = name;
@ -212,9 +214,15 @@ int spdylay_frame_unpack_nv(char ***nv_ptr, spdylay_buffer *in,
invalid_header_block = 1;
}
val = data+1;
multival = 1;
}
}
*data = '\0';
/* Check last header value is empty if NULL separator was
found. */
if(multival && val == data) {
invalid_header_block = 1;
}
++data;
*idx++ = name;

View File

@ -216,6 +216,10 @@ int main(int argc, char* argv[])
test_spdylay_frame_unpack_nv_check_name_spdy2) ||
!CU_add_test(pSuite, "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",
test_spdylay_frame_nv_set_origin) ||
!CU_add_test(pSuite, "stream_add_pushed_stream",

View File

@ -707,6 +707,8 @@ void test_spdylay_frame_nv_3to2(void)
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,
size_t len_size)
{
@ -790,6 +792,51 @@ void test_spdylay_frame_unpack_nv_check_name_spdy3(void)
(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)
{
spdylay_origin origin;

View File

@ -50,6 +50,8 @@ void test_spdylay_frame_nv_2to3(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_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);
#endif /* SPDYLAY_FRAME_TEST_H */