Handle indexing entry greater than header table limit without error

This commit is contained in:
Tatsuhiro Tsujikawa 2013-08-28 23:16:23 +09:00
parent 4fe056d208
commit 83b0c89e3c
4 changed files with 116 additions and 10 deletions

View File

@ -340,10 +340,6 @@ static nghttp2_hd_entry* add_hd_table_incremental(nghttp2_hd_context *context,
size_t i;
nghttp2_hd_entry *new_ent;
size_t room = entry_room(nv->namelen, nv->valuelen);
if(context->hd_tablelen == context->hd_table_capacity ||
room > NGHTTP2_HD_MAX_BUFFER_SIZE) {
return NULL;
}
context->hd_table_bufsize += room;
for(i = 0; i < context->hd_tablelen &&
context->hd_table_bufsize > NGHTTP2_HD_MAX_BUFFER_SIZE; ++i) {
@ -383,8 +379,20 @@ static nghttp2_hd_entry* add_hd_table_incremental(nghttp2_hd_context *context,
if(rv != 0) {
return NULL;
}
context->hd_table[context->hd_tablelen++] = new_ent;
new_ent->flags |= NGHTTP2_HD_FLAG_REFSET;
if(room > NGHTTP2_HD_MAX_BUFFER_SIZE) {
/* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is
immediately evicted. */
new_ent->index = NGHTTP2_HD_INVALID_INDEX;
--new_ent->ref;
} else {
/* Because of current NGHTTP2_HD_MAX_BUFFER_SIZE,
NGHTTP2_HD_ENTRY_OVERHEAD and NGHTTP2_INITIAL_HD_TABLE_SIZE,
context->hd_tablelen is strictly less than
context->hd_table_capacity. */
assert(context->hd_tablelen < context->hd_table_capacity);
context->hd_table[context->hd_tablelen++] = new_ent;
new_ent->flags |= NGHTTP2_HD_FLAG_REFSET;
}
return new_ent;
}
@ -396,8 +404,7 @@ static nghttp2_hd_entry* add_hd_table_subst(nghttp2_hd_context *context,
int k;
nghttp2_hd_entry *new_ent;
size_t room = entry_room(nv->namelen, nv->valuelen);
if(room > NGHTTP2_HD_MAX_BUFFER_SIZE ||
context->hd_tablelen <= subindex) {
if(context->hd_tablelen <= subindex) {
return NULL;
}
context->hd_table_bufsize -=
@ -429,6 +436,9 @@ static nghttp2_hd_entry* add_hd_table_subst(nghttp2_hd_context *context,
}
if(i > 0) {
size_t j;
/* k < 0 means that the index to substitute originally was
evicted. Therefore, index 0 is the position to substitute
now. */
if(k < 0) {
j = 1;
} else {
@ -470,8 +480,14 @@ static nghttp2_hd_entry* add_hd_table_subst(nghttp2_hd_context *context,
if(rv != 0) {
return NULL;
}
context->hd_table[new_ent->index] = new_ent;
new_ent->flags |= NGHTTP2_HD_FLAG_REFSET;
if(room > NGHTTP2_HD_MAX_BUFFER_SIZE) {
new_ent->index = NGHTTP2_HD_INVALID_INDEX;
--new_ent->ref;
context->hd_tablelen = 0;
} else {
context->hd_table[new_ent->index] = new_ent;
new_ent->flags |= NGHTTP2_HD_FLAG_REFSET;
}
return new_ent;
}

View File

@ -238,6 +238,10 @@ int main(int argc, char* argv[])
test_nghttp2_hd_inflate_indname_subst_eviction_neg) ||
!CU_add_test(pSuite, "hd_inflate_newname_subst",
test_nghttp2_hd_inflate_newname_subst) ||
!CU_add_test(pSuite, "hd_inflate_clearall_subst",
test_nghttp2_hd_inflate_clearall_subst) ||
!CU_add_test(pSuite, "hd_inflate_clearall_inc",
test_nghttp2_hd_inflate_clearall_inc) ||
!CU_add_test(pSuite, "hd_deflate_inflate",
test_nghttp2_hd_deflate_inflate) ||
!CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate) ||

View File

@ -380,6 +380,90 @@ void test_nghttp2_hd_inflate_newname_subst(void)
nghttp2_hd_inflate_free(&inflater);
}
void test_nghttp2_hd_inflate_clearall_inc(void)
{
nghttp2_hd_context inflater;
uint8_t *buf = NULL;
size_t buflen = 0;
size_t offset = 0;
nghttp2_nv nv;
nghttp2_nv *resnva;
uint8_t value[4060];
/* Total 4097 bytes space required to hold this entry */
nv.name = (uint8_t*)"alpha";
nv.namelen = strlen((char*)nv.name);
memset(value, '0', sizeof(value));
nv.value = value;
nv.valuelen = sizeof(value);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_SERVER);
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &buflen, &offset,
&nv, 1));
CU_ASSERT(1 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf, offset));
assert_nv_equal(&nv, resnva, 1);
CU_ASSERT(0 == inflater.hd_tablelen);
nghttp2_nv_array_del(resnva);
nghttp2_hd_end_headers(&inflater);
/* Do it again */
CU_ASSERT(1 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf, offset));
assert_nv_equal(&nv, resnva, 1);
CU_ASSERT(0 == inflater.hd_tablelen);
nghttp2_nv_array_del(resnva);
nghttp2_hd_end_headers(&inflater);
/* This time, 4096 bytes space required, which is just fits in the
header table */
nv.valuelen = sizeof(value) - 1;
offset = 0;
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &buflen, &offset,
&nv, 1));
CU_ASSERT(1 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf, offset));
assert_nv_equal(&nv, resnva, 1);
CU_ASSERT(1 == inflater.hd_tablelen);
nghttp2_nv_array_del(resnva);
free(buf);
nghttp2_hd_inflate_free(&inflater);
}
void test_nghttp2_hd_inflate_clearall_subst(void)
{
nghttp2_hd_context inflater;
uint8_t *buf = NULL;
size_t buflen = 0;
size_t offset = 0;
nghttp2_nv nv;
nghttp2_nv *resnva;
uint8_t value[4060];
/* Total 4097 bytes space required to hold this entry */
nv.name = (uint8_t*)"alpha";
nv.namelen = strlen((char*)nv.name);
memset(value, '0', sizeof(value));
nv.value = value;
nv.valuelen = sizeof(value);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_SERVER);
CU_ASSERT(0 == nghttp2_hd_emit_subst_newname_block(&buf, &buflen, &offset,
&nv, 1));
CU_ASSERT(1 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf, offset));
assert_nv_equal(&nv, resnva, 1);
CU_ASSERT(0 == inflater.hd_tablelen);
nghttp2_nv_array_del(resnva);
free(buf);
nghttp2_hd_inflate_free(&inflater);
}
static void check_deflate_inflate(nghttp2_hd_context *deflater,
nghttp2_hd_context *inflater,
nghttp2_nv *nva, size_t nvlen)

View File

@ -34,6 +34,8 @@ void test_nghttp2_hd_inflate_indname_subst(void);
void test_nghttp2_hd_inflate_indname_subst_eviction(void);
void test_nghttp2_hd_inflate_indname_subst_eviction_neg(void);
void test_nghttp2_hd_inflate_newname_subst(void);
void test_nghttp2_hd_inflate_clearall_inc(void);
void test_nghttp2_hd_inflate_clearall_subst(void);
void test_nghttp2_hd_deflate_inflate(void);
#endif /* NGHTTP2_HD_TEST_H */