diff --git a/lib/nghttp2_hd.c b/lib/nghttp2_hd.c index b7bc1373..713c91db 100644 --- a/lib/nghttp2_hd.c +++ b/lib/nghttp2_hd.c @@ -352,37 +352,29 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater) NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE; inflater->ent_keep = NULL; - inflater->name_keep = NULL; - inflater->value_keep = NULL; + inflater->nv_keep = NULL; inflater->end_headers_index = 0; inflater->opcode = NGHTTP2_HD_OPCODE_NONE; inflater->state = NGHTTP2_HD_STATE_OPCODE; - rv = nghttp2_bufs_init(&inflater->namebufs, NGHTTP2_HD_MAX_NAME, 1); + rv = nghttp2_bufs_init(&inflater->nvbufs, NGHTTP2_HD_MAX_NV / 2, 2); if(rv != 0) { - goto namebuf_fail; - } - - rv = nghttp2_bufs_init(&inflater->valuebufs, NGHTTP2_HD_MAX_VALUE / 2, 2); - - if(rv != 0) { - goto valuebuf_fail; + goto nvbufs_fail; } inflater->huffman_encoded = 0; inflater->index = 0; inflater->left = 0; + inflater->newnamelen = 0; inflater->index_required = 0; inflater->no_index = 0; inflater->ent_name = NULL; return 0; - valuebuf_fail: - nghttp2_bufs_free(&inflater->namebufs); - namebuf_fail: + nvbufs_fail: hd_context_free(&inflater->ctx); fail: return rv; @@ -397,10 +389,9 @@ static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) } inflater->ent_keep = NULL; } - free(inflater->name_keep); - free(inflater->value_keep); - inflater->name_keep = NULL; - inflater->value_keep = NULL; + + free(inflater->nv_keep); + inflater->nv_keep = NULL; } void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) @@ -411,8 +402,7 @@ void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) { hd_inflate_keep_free(inflater); - nghttp2_bufs_free(&inflater->namebufs); - nghttp2_bufs_free(&inflater->valuebufs); + nghttp2_bufs_free(&inflater->nvbufs); hd_context_free(&inflater->ctx); } @@ -1488,27 +1478,27 @@ static int hd_inflate_remove_bufs(nghttp2_hd_inflater *inflater, nghttp2_nv *nv, int value_only) { ssize_t rv; + size_t buflen; + uint8_t *buf; - if(value_only) { - nv->name = NULL; - } else { - rv = nghttp2_bufs_remove(&inflater->namebufs, &nv->name); + rv = nghttp2_bufs_remove(&inflater->nvbufs, &buf); - if(rv < 0) { - return NGHTTP2_ERR_NOMEM; - } - - nv->namelen = rv; - } - - rv = nghttp2_bufs_remove(&inflater->valuebufs, &nv->value); if(rv < 0) { - free(nv->name); - return NGHTTP2_ERR_NOMEM; } - nv->valuelen = rv; + buflen = rv; + + if(value_only) { + nv->name = NULL; + nv->namelen = 0; + } else { + nv->name = buf; + nv->namelen = inflater->newnamelen; + } + + nv->value = buf + nv->namelen; + nv->valuelen = buflen - nv->namelen; return 0; } @@ -1545,9 +1535,10 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater, nghttp2_hd_entry *new_ent; uint8_t ent_flags; - ent_flags = - NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_VALUE_ALLOC | - NGHTTP2_HD_FLAG_NAME_GIFT | NGHTTP2_HD_FLAG_VALUE_GIFT; + /* nv->value points to the middle of the buffer pointed by + nv->name. So we just need to keep track of nv->name for memory + management. */ + ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT; new_ent = add_hd_table_incremental(&inflater->ctx, NULL, &nv, ent_flags); @@ -1559,15 +1550,13 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater, } free(nv.name); - free(nv.value); return NGHTTP2_ERR_NOMEM; } emit_literal_header(nv_out, &nv); - inflater->name_keep = nv.name; - inflater->value_keep = nv.value; + inflater->nv_keep = nv.name; return 0; } @@ -1642,7 +1631,7 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater, emit_literal_header(nv_out, &nv); - inflater->value_keep = nv.value; + inflater->nv_keep = nv.value; return 0; } @@ -1793,7 +1782,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, case NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN: rfin = 0; rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, - NGHTTP2_HD_MAX_NAME); + NGHTTP2_HD_MAX_NV); if(rv < 0) { goto fail; } @@ -1815,7 +1804,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, } break; case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF: - rv = hd_inflate_read_huff(inflater, &inflater->namebufs, in, last); + rv = hd_inflate_read_huff(inflater, &inflater->nvbufs, in, last); if(rv < 0) { goto fail; } @@ -1831,11 +1820,13 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, goto almost_ok; } + inflater->newnamelen = nghttp2_bufs_len(&inflater->nvbufs); + inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN; break; case NGHTTP2_HD_STATE_NEWNAME_READ_NAME: - rv = hd_inflate_read(inflater, &inflater->namebufs, in, last); + rv = hd_inflate_read(inflater, &inflater->nvbufs, in, last); if(rv < 0) { goto fail; } @@ -1850,6 +1841,8 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, goto almost_ok; } + inflater->newnamelen = nghttp2_bufs_len(&inflater->nvbufs); + inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN; break; @@ -1863,7 +1856,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, case NGHTTP2_HD_STATE_READ_VALUELEN: rfin = 0; rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, - NGHTTP2_HD_MAX_VALUE); + NGHTTP2_HD_MAX_NV); if(rv < 0) { goto fail; } @@ -1898,7 +1891,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, } break; case NGHTTP2_HD_STATE_READ_VALUEHUFF: - rv = hd_inflate_read_huff(inflater, &inflater->valuebufs, in, last); + rv = hd_inflate_read_huff(inflater, &inflater->nvbufs, in, last); if(rv < 0) { goto fail; } @@ -1929,7 +1922,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, return in - first; case NGHTTP2_HD_STATE_READ_VALUE: - rv = hd_inflate_read(inflater, &inflater->valuebufs, in, last); + rv = hd_inflate_read(inflater, &inflater->nvbufs, in, last); if(rv < 0) { DEBUGF(fprintf(stderr, "inflatehd: value read failure %zd: %s\n", rv, nghttp2_strerror(rv))); diff --git a/lib/nghttp2_hd.h b/lib/nghttp2_hd.h index d0087bca..542e1894 100644 --- a/lib/nghttp2_hd.h +++ b/lib/nghttp2_hd.h @@ -37,10 +37,10 @@ #define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE NGHTTP2_DEFAULT_HEADER_TABLE_SIZE #define NGHTTP2_HD_ENTRY_OVERHEAD 32 -/* The maximum value length of name/value pair. This is not specified - by the spec. We just chose the arbitrary size */ -#define NGHTTP2_HD_MAX_NAME 256 -#define NGHTTP2_HD_MAX_VALUE 8192 +/* The maximum length of one name/value pair. This is the sum of the + length of name and value. This is not specified by the spec. We + just chose the arbitrary size */ +#define NGHTTP2_HD_MAX_NV 8192 /* Default size of maximum table buffer size for encoder. Even if remote decoder notifies larger buffer size for its decoding, @@ -146,20 +146,17 @@ struct nghttp2_hd_deflater { struct nghttp2_hd_inflater { nghttp2_hd_context ctx; - /* header name buffer */ - nghttp2_bufs namebufs; - /* header value buffer */ - nghttp2_bufs valuebufs; + /* header buffer */ + nghttp2_bufs nvbufs; /* Stores current state of huffman decoding */ nghttp2_hd_huff_decode_context huff_decode_ctx; /* Pointer to the nghttp2_hd_entry which is used current header emission. This is required because in some cases the ent_keep->ref == 0 and we have to keep track of it. */ nghttp2_hd_entry *ent_keep; - /* Pointers to the name/value pair which are used current header - emission. They are usually used to keep track of malloc'ed memory - for huffman decoding. */ - uint8_t *name_keep, *value_keep; + /* Pointer to the name/value pair buffer which is used in the + current header emission. */ + uint8_t *nv_keep; /* Pointers to the name/value pair which is referred as indexed name. This entry must be in header table. */ nghttp2_hd_entry *ent_name; @@ -170,6 +167,9 @@ struct nghttp2_hd_inflater { /* The index of header table to toggle off the entry from reference set at the end of decompression. */ size_t end_headers_index; + /* The length of new name encoded in literal. For huffman encoded + string, this is the length after it is decoded. */ + size_t newnamelen; /* The maximum header table size the inflater supports. This is the same value transmitted in SETTINGS_HEADER_TABLE_SIZE */ size_t settings_hd_table_bufsize_max; diff --git a/tests/nghttp2_frame_test.c b/tests/nghttp2_frame_test.c index 0d55b2e8..1f7fb3f1 100644 --- a/tests/nghttp2_frame_test.c +++ b/tests/nghttp2_frame_test.c @@ -173,7 +173,7 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void) nghttp2_bufs bufs; nghttp2_nv *nva; ssize_t nvlen; - size_t big_vallen = NGHTTP2_HD_MAX_VALUE; + size_t big_vallen = NGHTTP2_HD_MAX_NV; nghttp2_nv big_hds[16]; size_t big_hdslen = ARRLEN(big_hds); size_t i; diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index ad9aaa7c..9e6a29ca 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -2374,7 +2374,7 @@ void test_nghttp2_session_send_headers_header_comp_error(void) nghttp2_frame *frame = malloc(sizeof(nghttp2_frame)); nghttp2_nv *nva; ssize_t nvlen; - size_t vallen = NGHTTP2_HD_MAX_VALUE; + size_t vallen = NGHTTP2_HD_MAX_NV; nghttp2_nv nv[28]; size_t nnv = ARRLEN(nv); size_t i;