Always allocate buffer for name, and value
This commit is contained in:
parent
eb393985b7
commit
8da20975f9
|
@ -73,7 +73,7 @@ typedef struct {
|
|||
|
||||
/*
|
||||
* Initializes the |buf|. No memory is allocated in this function. Use
|
||||
* nghttp2_buf_reserve() or nghttp2_buf_reserve2() to allocate memory.
|
||||
* nghttp2_buf_reserve() to allocate memory.
|
||||
*/
|
||||
void nghttp2_buf_init(nghttp2_buf *buf);
|
||||
|
||||
|
|
270
lib/nghttp2_hd.c
270
lib/nghttp2_hd.c
|
@ -1099,30 +1099,24 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
|
|||
inflater->min_hd_table_bufsize_max = UINT32_MAX;
|
||||
|
||||
inflater->ent_keep = NULL;
|
||||
inflater->nv_keep = NULL;
|
||||
inflater->nv_name_keep = NULL;
|
||||
inflater->nv_value_keep = NULL;
|
||||
|
||||
inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
|
||||
inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
|
||||
|
||||
rv = nghttp2_bufs_init3(&inflater->nvbufs, NGHTTP2_HD_MAX_NV / 8, 8, 1, 0,
|
||||
mem);
|
||||
|
||||
if (rv != 0) {
|
||||
goto nvbufs_fail;
|
||||
}
|
||||
nghttp2_buf_init(&inflater->namebuf);
|
||||
nghttp2_buf_init(&inflater->valuebuf);
|
||||
|
||||
inflater->huffman_encoded = 0;
|
||||
inflater->index = 0;
|
||||
inflater->left = 0;
|
||||
inflater->shift = 0;
|
||||
inflater->newnamelen = 0;
|
||||
inflater->index_required = 0;
|
||||
inflater->no_index = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nvbufs_fail:
|
||||
hd_context_free(&inflater->ctx);
|
||||
fail:
|
||||
return rv;
|
||||
}
|
||||
|
@ -1139,8 +1133,11 @@ static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
|
|||
inflater->ent_keep = NULL;
|
||||
}
|
||||
|
||||
nghttp2_mem_free(mem, inflater->nv_keep);
|
||||
inflater->nv_keep = NULL;
|
||||
nghttp2_mem_free(mem, inflater->nv_value_keep);
|
||||
inflater->nv_value_keep = NULL;
|
||||
|
||||
nghttp2_mem_free(mem, inflater->nv_name_keep);
|
||||
inflater->nv_name_keep = NULL;
|
||||
}
|
||||
|
||||
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
|
||||
|
@ -1148,8 +1145,13 @@ void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
|
|||
}
|
||||
|
||||
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
|
||||
nghttp2_mem *mem;
|
||||
|
||||
mem = inflater->ctx.mem;
|
||||
|
||||
hd_inflate_keep_free(inflater);
|
||||
nghttp2_bufs_free(&inflater->nvbufs);
|
||||
nghttp2_buf_free(&inflater->valuebuf, mem);
|
||||
nghttp2_buf_free(&inflater->namebuf, mem);
|
||||
hd_context_free(&inflater->ctx);
|
||||
}
|
||||
|
||||
|
@ -2036,11 +2038,9 @@ static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
|
|||
* Out of memory
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* Huffman decoding failed
|
||||
* NGHTTP2_ERR_BUFFER_ERROR
|
||||
* Out of buffer space.
|
||||
*/
|
||||
static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_bufs *bufs, uint8_t *in,
|
||||
nghttp2_buf *buf, uint8_t *in,
|
||||
uint8_t *last) {
|
||||
ssize_t readlen;
|
||||
int final = 0;
|
||||
|
@ -2048,7 +2048,7 @@ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
|
|||
last = in + inflater->left;
|
||||
final = 1;
|
||||
}
|
||||
readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, bufs, in,
|
||||
readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
|
||||
(size_t)(last - in), final);
|
||||
|
||||
if (readlen < 0) {
|
||||
|
@ -2070,17 +2070,13 @@ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
|
|||
* Out of memory
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* Header decompression failed
|
||||
* NGHTTP2_ERR_BUFFER_ERROR
|
||||
* Out of buffer space.
|
||||
*/
|
||||
static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_bufs *bufs, uint8_t *in, uint8_t *last) {
|
||||
int rv;
|
||||
static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf,
|
||||
uint8_t *in, uint8_t *last) {
|
||||
size_t len = nghttp2_min((size_t)(last - in), inflater->left);
|
||||
rv = nghttp2_bufs_add(bufs, in, len);
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
buf->last = nghttp2_cpymem(buf->last, in, len);
|
||||
|
||||
inflater->left -= len;
|
||||
return (ssize_t)len;
|
||||
}
|
||||
|
@ -2105,112 +2101,6 @@ static int hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
|
|||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
nghttp2_buf *pbuf;
|
||||
|
||||
if (inflater->index_required ||
|
||||
inflater->nvbufs.head != inflater->nvbufs.cur) {
|
||||
|
||||
rv = nghttp2_bufs_remove(&inflater->nvbufs, &buf);
|
||||
|
||||
if (rv < 0) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
nghttp2_bufs_reset(&inflater->nvbufs);
|
||||
|
||||
buflen = (size_t)rv;
|
||||
|
||||
if (value_only) {
|
||||
/* we don't use this value, so no need to NULL-terminate */
|
||||
nv->name = NULL;
|
||||
nv->namelen = 0;
|
||||
|
||||
nv->value = buf;
|
||||
nv->valuelen = buflen - 1;
|
||||
} else {
|
||||
nv->name = buf;
|
||||
nv->namelen = inflater->newnamelen;
|
||||
|
||||
nv->value = buf + nv->namelen + 1;
|
||||
nv->valuelen = buflen - nv->namelen - 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If we are not going to store header in header table and
|
||||
name/value are in first chunk, we just refer them from nv,
|
||||
instead of mallocing another memory. */
|
||||
|
||||
pbuf = &inflater->nvbufs.head->buf;
|
||||
|
||||
if (value_only) {
|
||||
/* we don't use this value, so no need to NULL-terminate */
|
||||
nv->name = NULL;
|
||||
nv->namelen = 0;
|
||||
|
||||
nv->value = pbuf->pos;
|
||||
nv->valuelen = nghttp2_buf_len(pbuf) - 1;
|
||||
} else {
|
||||
nv->name = pbuf->pos;
|
||||
nv->namelen = inflater->newnamelen;
|
||||
|
||||
nv->value = pbuf->pos + nv->namelen + 1;
|
||||
nv->valuelen = nghttp2_buf_len(pbuf) - nv->namelen - 2;
|
||||
}
|
||||
|
||||
/* Resetting does not change the content of first buffer */
|
||||
nghttp2_bufs_reset(&inflater->nvbufs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hd_inflate_remove_bufs_with_name(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_nv *nv,
|
||||
nghttp2_hd_entry *ent_name) {
|
||||
#ifndef NDEBUG
|
||||
size_t rv;
|
||||
#endif
|
||||
size_t buflen;
|
||||
uint8_t *buf;
|
||||
nghttp2_mem *mem;
|
||||
|
||||
mem = inflater->ctx.mem;
|
||||
|
||||
/* Allocate buffer including name in ent_name, plus terminating
|
||||
NULL. */
|
||||
buflen = ent_name->nv.namelen + 1 + nghttp2_bufs_len(&inflater->nvbufs);
|
||||
|
||||
buf = nghttp2_mem_malloc(mem, buflen);
|
||||
if (buf == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
/* Copy including terminal NULL */
|
||||
memcpy(buf, ent_name->nv.name, ent_name->nv.namelen + 1);
|
||||
#ifndef NDEBUG
|
||||
rv =
|
||||
#endif
|
||||
nghttp2_bufs_remove_copy(&inflater->nvbufs,
|
||||
buf + ent_name->nv.namelen + 1);
|
||||
assert(ent_name->nv.namelen + 1 + rv == buflen);
|
||||
|
||||
nghttp2_bufs_reset(&inflater->nvbufs);
|
||||
|
||||
nv->name = buf;
|
||||
nv->namelen = ent_name->nv.namelen;
|
||||
|
||||
nv->value = buf + nv->namelen + 1;
|
||||
nv->valuelen = buflen - nv->namelen - 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finalize literal header representation - new name- reception. If
|
||||
* header is emitted, |*nv_out| is filled with that value and 0 is
|
||||
|
@ -2224,16 +2114,18 @@ static int hd_inflate_remove_bufs_with_name(nghttp2_hd_inflater *inflater,
|
|||
*/
|
||||
static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_nv *nv_out, int *token_out) {
|
||||
int rv;
|
||||
nghttp2_nv nv;
|
||||
nghttp2_mem *mem;
|
||||
|
||||
mem = inflater->ctx.mem;
|
||||
|
||||
rv = hd_inflate_remove_bufs(inflater, &nv, 0 /* name and value */);
|
||||
if (rv != 0) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
nv.name = inflater->namebuf.pos;
|
||||
nv.namelen = nghttp2_buf_len(&inflater->namebuf);
|
||||
nv.value = inflater->valuebuf.pos;
|
||||
nv.valuelen = nghttp2_buf_len(&inflater->valuebuf);
|
||||
|
||||
nghttp2_buf_init(&inflater->valuebuf);
|
||||
nghttp2_buf_init(&inflater->namebuf);
|
||||
|
||||
if (inflater->no_index) {
|
||||
nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
|
||||
|
@ -2245,10 +2137,8 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
|
|||
nghttp2_hd_entry *new_ent;
|
||||
uint8_t ent_flags;
|
||||
|
||||
/* 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;
|
||||
ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT |
|
||||
NGHTTP2_HD_FLAG_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT;
|
||||
|
||||
new_ent = add_hd_table_incremental(&inflater->ctx, &nv,
|
||||
lookup_token(nv.name, nv.namelen),
|
||||
|
@ -2261,6 +2151,7 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
|
|||
return 0;
|
||||
}
|
||||
|
||||
nghttp2_mem_free(mem, nv.value);
|
||||
nghttp2_mem_free(mem, nv.name);
|
||||
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
|
@ -2268,9 +2159,8 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
|
|||
|
||||
emit_literal_header(nv_out, token_out, &nv);
|
||||
|
||||
if (nv.name != inflater->nvbufs.head->buf.pos) {
|
||||
inflater->nv_keep = nv.name;
|
||||
}
|
||||
inflater->nv_name_keep = nv.name;
|
||||
inflater->nv_value_keep = nv.value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2288,7 +2178,6 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
|
|||
*/
|
||||
static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
|
||||
nghttp2_nv *nv_out, int *token_out) {
|
||||
int rv;
|
||||
nghttp2_nv nv;
|
||||
nghttp2_hd_entry *ent_name;
|
||||
nghttp2_mem *mem;
|
||||
|
@ -2307,24 +2196,20 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
|
|||
nghttp2_hd_entry *new_ent;
|
||||
uint8_t ent_flags;
|
||||
|
||||
if (inflater->index < NGHTTP2_STATIC_TABLE_LENGTH) {
|
||||
ent_flags = NGHTTP2_HD_FLAG_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT;
|
||||
|
||||
if (inflater->index >= NGHTTP2_STATIC_TABLE_LENGTH) {
|
||||
/* We don't copy name in static table */
|
||||
rv = hd_inflate_remove_bufs(inflater, &nv, 1 /* value only */);
|
||||
if (rv != 0) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
ent_flags |= NGHTTP2_HD_FLAG_NAME_ALLOC;
|
||||
}
|
||||
|
||||
nv.name = ent_name->nv.name;
|
||||
nv.namelen = ent_name->nv.namelen;
|
||||
|
||||
ent_flags = NGHTTP2_HD_FLAG_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT;
|
||||
} else {
|
||||
rv = hd_inflate_remove_bufs_with_name(inflater, &nv, ent_name);
|
||||
if (rv != 0) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
/* nv->name and nv->value are in the same buffer. */
|
||||
ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT;
|
||||
}
|
||||
nv.value = inflater->valuebuf.pos;
|
||||
nv.valuelen = nghttp2_buf_len(&inflater->valuebuf);
|
||||
|
||||
nghttp2_buf_init(&inflater->valuebuf);
|
||||
|
||||
new_ent = add_hd_table_incremental(&inflater->ctx, &nv, ent_name->token,
|
||||
ent_flags, NULL, 0);
|
||||
|
@ -2339,28 +2224,21 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (inflater->index < NGHTTP2_STATIC_TABLE_LENGTH) {
|
||||
nghttp2_mem_free(mem, nv.value);
|
||||
} else {
|
||||
nghttp2_mem_free(mem, nv.name);
|
||||
}
|
||||
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
rv = hd_inflate_remove_bufs(inflater, &nv, 1 /* value only */);
|
||||
if (rv != 0) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
nv.name = ent_name->nv.name;
|
||||
nv.namelen = ent_name->nv.namelen;
|
||||
nv.value = inflater->valuebuf.pos;
|
||||
nv.valuelen = nghttp2_buf_len(&inflater->valuebuf);
|
||||
|
||||
nghttp2_buf_init(&inflater->valuebuf);
|
||||
|
||||
emit_literal_header(nv_out, token_out, &nv);
|
||||
|
||||
if (nv.value != inflater->nvbufs.head->buf.pos) {
|
||||
inflater->nv_keep = nv.value;
|
||||
}
|
||||
inflater->nv_value_keep = nv.value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2383,6 +2261,9 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
|||
uint8_t *last = in + inlen;
|
||||
int rfin = 0;
|
||||
int busy = 0;
|
||||
nghttp2_mem *mem;
|
||||
|
||||
mem = inflater->ctx.mem;
|
||||
|
||||
if (inflater->ctx.bad) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
|
@ -2541,12 +2422,20 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
|||
nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
|
||||
|
||||
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
|
||||
rv = nghttp2_buf_reserve(&inflater->namebuf, inflater->left * 2 + 1,
|
||||
mem);
|
||||
} else {
|
||||
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
|
||||
rv = nghttp2_buf_reserve(&inflater->namebuf, inflater->left + 1, mem);
|
||||
}
|
||||
|
||||
if (rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
|
||||
rv = hd_inflate_read_huff(inflater, &inflater->nvbufs, in, last);
|
||||
rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
|
||||
if (rv < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -2562,18 +2451,13 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
|||
goto almost_ok;
|
||||
}
|
||||
|
||||
inflater->newnamelen = nghttp2_bufs_len(&inflater->nvbufs);
|
||||
|
||||
rv = nghttp2_bufs_addb(&inflater->nvbufs, '\0');
|
||||
if (rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
*inflater->namebuf.last = '\0';
|
||||
|
||||
inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
|
||||
|
||||
break;
|
||||
case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
|
||||
rv = hd_inflate_read(inflater, &inflater->nvbufs, in, last);
|
||||
rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
|
||||
if (rv < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -2588,12 +2472,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
|||
goto almost_ok;
|
||||
}
|
||||
|
||||
inflater->newnamelen = nghttp2_bufs_len(&inflater->nvbufs);
|
||||
|
||||
rv = nghttp2_bufs_addb(&inflater->nvbufs, '\0');
|
||||
if (rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
*inflater->namebuf.last = '\0';
|
||||
|
||||
inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
|
||||
|
||||
|
@ -2625,15 +2504,24 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
|||
nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
|
||||
|
||||
inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
|
||||
|
||||
rv = nghttp2_buf_reserve(&inflater->valuebuf, inflater->left * 2 + 1,
|
||||
mem);
|
||||
} else {
|
||||
inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
|
||||
|
||||
rv = nghttp2_buf_reserve(&inflater->valuebuf, inflater->left + 1, mem);
|
||||
}
|
||||
|
||||
if (rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
busy = 1;
|
||||
|
||||
break;
|
||||
case NGHTTP2_HD_STATE_READ_VALUEHUFF:
|
||||
rv = hd_inflate_read_huff(inflater, &inflater->nvbufs, in, last);
|
||||
rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
|
||||
if (rv < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -2649,10 +2537,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
|||
goto almost_ok;
|
||||
}
|
||||
|
||||
rv = nghttp2_bufs_addb(&inflater->nvbufs, '\0');
|
||||
if (rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
*inflater->valuebuf.last = '\0';
|
||||
|
||||
if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
|
||||
rv = hd_inflate_commit_newname(inflater, nv_out, token_out);
|
||||
|
@ -2669,7 +2554,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
|||
|
||||
return (ssize_t)(in - first);
|
||||
case NGHTTP2_HD_STATE_READ_VALUE:
|
||||
rv = hd_inflate_read(inflater, &inflater->nvbufs, in, last);
|
||||
rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
|
||||
if (rv < 0) {
|
||||
DEBUGF(fprintf(stderr, "inflatehd: value read failure %zd: %s\n", rv,
|
||||
nghttp2_strerror((int)rv)));
|
||||
|
@ -2686,10 +2571,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
|||
goto almost_ok;
|
||||
}
|
||||
|
||||
rv = nghttp2_bufs_addb(&inflater->nvbufs, '\0');
|
||||
if (rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
*inflater->valuebuf.last = '\0';
|
||||
|
||||
if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
|
||||
rv = hd_inflate_commit_newname(inflater, nv_out, token_out);
|
||||
|
|
|
@ -276,7 +276,7 @@ struct nghttp2_hd_deflater {
|
|||
struct nghttp2_hd_inflater {
|
||||
nghttp2_hd_context ctx;
|
||||
/* header buffer */
|
||||
nghttp2_bufs nvbufs;
|
||||
nghttp2_buf namebuf, valuebuf;
|
||||
/* 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
|
||||
|
@ -285,14 +285,11 @@ struct nghttp2_hd_inflater {
|
|||
nghttp2_hd_entry *ent_keep;
|
||||
/* Pointer to the name/value pair buffer which is used in the
|
||||
current header emission. */
|
||||
uint8_t *nv_keep;
|
||||
uint8_t *nv_name_keep, *nv_value_keep;
|
||||
/* The number of bytes to read */
|
||||
size_t left;
|
||||
/* The index in indexed repr or indexed name */
|
||||
size_t 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;
|
||||
|
@ -472,9 +469,8 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
|
|||
/*
|
||||
* Decodes the given data |src| with length |srclen|. The |ctx| must
|
||||
* be initialized by nghttp2_hd_huff_decode_context_init(). The result
|
||||
* will be added to |dest|. This function may expand |dest| as
|
||||
* needed. The caller is responsible to release the memory of |dest|
|
||||
* by calling nghttp2_bufs_free().
|
||||
* will be written to |buf|. This function assumes that |buf| has the
|
||||
* enough room to store the decoded byte string.
|
||||
*
|
||||
* The caller must set the |final| to nonzero if the given input is
|
||||
* the final block.
|
||||
|
@ -486,13 +482,11 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
|
|||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_BUFFER_ERROR
|
||||
* Maximum buffer capacity size exceeded.
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* Decoding process has failed.
|
||||
*/
|
||||
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_bufs *bufs, const uint8_t *src,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int final);
|
||||
|
||||
#endif /* NGHTTP2_HD_H */
|
||||
|
|
|
@ -166,31 +166,10 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
|
|||
ctx->accept = 1;
|
||||
}
|
||||
|
||||
/* Use macro to make the code simpler..., but error case is tricky.
|
||||
We spent most of the CPU in decoding, so we are doing this
|
||||
thing. */
|
||||
#define hd_huff_decode_sym_emit(bufs, sym, avail) \
|
||||
do { \
|
||||
if ((avail)) { \
|
||||
nghttp2_bufs_fast_addb((bufs), (sym)); \
|
||||
--(avail); \
|
||||
} else { \
|
||||
rv = nghttp2_bufs_addb((bufs), (sym)); \
|
||||
if (rv != 0) { \
|
||||
return rv; \
|
||||
} \
|
||||
(avail) = nghttp2_bufs_cur_avail((bufs)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
||||
nghttp2_bufs *bufs, const uint8_t *src,
|
||||
nghttp2_buf *buf, const uint8_t *src,
|
||||
size_t srclen, int final) {
|
||||
size_t i;
|
||||
int rv;
|
||||
size_t avail;
|
||||
|
||||
avail = nghttp2_bufs_cur_avail(bufs);
|
||||
|
||||
/* We use the decoding algorithm described in
|
||||
http://graphics.ics.uci.edu/pub/Prefix.pdf */
|
||||
|
@ -202,8 +181,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
|||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
if (t->flags & NGHTTP2_HUFF_SYM) {
|
||||
/* this is macro, and may return from this function on error */
|
||||
hd_huff_decode_sym_emit(bufs, t->sym, avail);
|
||||
*buf->last++ = t->sym;
|
||||
}
|
||||
|
||||
t = &huff_decode_table[t->state][src[i] & 0xf];
|
||||
|
@ -211,8 +189,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
|||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
if (t->flags & NGHTTP2_HUFF_SYM) {
|
||||
/* this is macro, and may return from this function on error */
|
||||
hd_huff_decode_sym_emit(bufs, t->sym, avail);
|
||||
*buf->last++ = t->sym;
|
||||
}
|
||||
|
||||
ctx->state = t->state;
|
||||
|
|
|
@ -1352,13 +1352,15 @@ void test_nghttp2_hd_decode_length(void) {
|
|||
void test_nghttp2_hd_huff_encode(void) {
|
||||
int rv;
|
||||
ssize_t len;
|
||||
nghttp2_bufs bufs, outbufs;
|
||||
nghttp2_buf outbuf;
|
||||
nghttp2_bufs bufs;
|
||||
nghttp2_hd_huff_decode_context ctx;
|
||||
const uint8_t t1[] = {22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
|
||||
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
|
||||
uint8_t b[256];
|
||||
|
||||
nghttp2_buf_wrap_init(&outbuf, b, sizeof(b));
|
||||
frame_pack_bufs_init(&bufs);
|
||||
frame_pack_bufs_init(&outbufs);
|
||||
|
||||
rv = nghttp2_hd_huff_encode(&bufs, t1, sizeof(t1));
|
||||
|
||||
|
@ -1366,14 +1368,13 @@ void test_nghttp2_hd_huff_encode(void) {
|
|||
|
||||
nghttp2_hd_huff_decode_context_init(&ctx);
|
||||
|
||||
len = nghttp2_hd_huff_decode(&ctx, &outbufs, bufs.cur->buf.pos,
|
||||
len = nghttp2_hd_huff_decode(&ctx, &outbuf, bufs.cur->buf.pos,
|
||||
nghttp2_bufs_len(&bufs), 1);
|
||||
|
||||
CU_ASSERT((ssize_t)nghttp2_bufs_len(&bufs) == len);
|
||||
CU_ASSERT((ssize_t)sizeof(t1) == nghttp2_bufs_len(&outbufs));
|
||||
CU_ASSERT((ssize_t)sizeof(t1) == nghttp2_buf_len(&outbuf));
|
||||
|
||||
CU_ASSERT(0 == memcmp(t1, outbufs.cur->buf.pos, sizeof(t1)));
|
||||
CU_ASSERT(0 == memcmp(t1, outbuf.pos, sizeof(t1)));
|
||||
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_bufs_free(&outbufs);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue