Fix integer decoding when it takes multiple reads
This commit is contained in:
parent
139c3b508a
commit
44310c6de5
|
@ -360,6 +360,7 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater)
|
||||||
inflater->huffman_encoded = 0;
|
inflater->huffman_encoded = 0;
|
||||||
inflater->index = 0;
|
inflater->index = 0;
|
||||||
inflater->left = 0;
|
inflater->left = 0;
|
||||||
|
inflater->shift = 0;
|
||||||
inflater->newnamelen = 0;
|
inflater->newnamelen = 0;
|
||||||
inflater->index_required = 0;
|
inflater->index_required = 0;
|
||||||
inflater->no_index = 0;
|
inflater->no_index = 0;
|
||||||
|
@ -496,16 +497,20 @@ static size_t encode_length(uint8_t *buf, size_t n, size_t prefix)
|
||||||
* set to nonzero.
|
* set to nonzero.
|
||||||
*
|
*
|
||||||
* This function returns the next byte of read byte. This function
|
* This function returns the next byte of read byte. This function
|
||||||
* stores the decoded integer in |*res| if it succeed, including
|
* stores the decoded integer in |*res| and number of shift to make in
|
||||||
* partial decoding, or stores -1 in |*res|, indicating decoding
|
* the next decoding in |*shift_ptr| if it succeed, including partial
|
||||||
* error.
|
* decoding, or stores -1 in |*res|, indicating decoding error.
|
||||||
*/
|
*/
|
||||||
static uint8_t* decode_length(ssize_t *res, int *final, ssize_t initial,
|
static uint8_t* decode_length(ssize_t *res, size_t *shift_ptr, int *final,
|
||||||
|
ssize_t initial, size_t shift,
|
||||||
uint8_t *in, uint8_t *last, size_t prefix)
|
uint8_t *in, uint8_t *last, size_t prefix)
|
||||||
{
|
{
|
||||||
int k = (1 << prefix) - 1, r;
|
int k = (1 << prefix) - 1;
|
||||||
ssize_t n = initial;
|
ssize_t n = initial;
|
||||||
|
|
||||||
|
*shift_ptr = 0;
|
||||||
*final = 0;
|
*final = 0;
|
||||||
|
|
||||||
if(n == 0) {
|
if(n == 0) {
|
||||||
if((*in & k) == k) {
|
if((*in & k) == k) {
|
||||||
n = k;
|
n = k;
|
||||||
|
@ -519,8 +524,8 @@ static uint8_t* decode_length(ssize_t *res, int *final, ssize_t initial,
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(r = 0; in != last; ++in, r += 7) {
|
for(; in != last; ++in, shift += 7) {
|
||||||
n += (*in & 0x7f) << r;
|
n += (*in & 0x7f) << shift;
|
||||||
if(n >= (1 << 16)) {
|
if(n >= (1 << 16)) {
|
||||||
*res = -1;
|
*res = -1;
|
||||||
return in + 1;
|
return in + 1;
|
||||||
|
@ -529,6 +534,9 @@ static uint8_t* decode_length(ssize_t *res, int *final, ssize_t initial,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*shift_ptr = shift;
|
||||||
|
|
||||||
if(in == last) {
|
if(in == last) {
|
||||||
*res = n;
|
*res = n;
|
||||||
return in;
|
return in;
|
||||||
|
@ -1350,7 +1358,8 @@ static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater,
|
||||||
{
|
{
|
||||||
uint8_t *nin;
|
uint8_t *nin;
|
||||||
*rfin = 0;
|
*rfin = 0;
|
||||||
nin = decode_length(&inflater->left, rfin, inflater->left, in, last, prefix);
|
nin = decode_length(&inflater->left, &inflater->shift, rfin, inflater->left,
|
||||||
|
inflater->shift, in, last, prefix);
|
||||||
if(inflater->left == -1) {
|
if(inflater->left == -1) {
|
||||||
DEBUGF(fprintf(stderr, "inflatehd: invalid integer\n"));
|
DEBUGF(fprintf(stderr, "inflatehd: invalid integer\n"));
|
||||||
return NGHTTP2_ERR_HEADER_COMP;
|
return NGHTTP2_ERR_HEADER_COMP;
|
||||||
|
@ -1691,6 +1700,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inflater->left = 0;
|
inflater->left = 0;
|
||||||
|
inflater->shift = 0;
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_HD_STATE_CLEAR_REFSET:
|
case NGHTTP2_HD_STATE_CLEAR_REFSET:
|
||||||
clear_refset(&inflater->ctx);
|
clear_refset(&inflater->ctx);
|
||||||
|
@ -1770,6 +1780,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
|
||||||
hd_inflate_set_huffman_encoded(inflater, in);
|
hd_inflate_set_huffman_encoded(inflater, in);
|
||||||
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
|
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
|
||||||
inflater->left = 0;
|
inflater->left = 0;
|
||||||
|
inflater->shift = 0;
|
||||||
DEBUGF(fprintf(stderr, "inflatehd: huffman encoded=%d\n",
|
DEBUGF(fprintf(stderr, "inflatehd: huffman encoded=%d\n",
|
||||||
inflater->huffman_encoded != 0));
|
inflater->huffman_encoded != 0));
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
|
@ -1844,6 +1855,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
|
||||||
hd_inflate_set_huffman_encoded(inflater, in);
|
hd_inflate_set_huffman_encoded(inflater, in);
|
||||||
inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
|
inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
|
||||||
inflater->left = 0;
|
inflater->left = 0;
|
||||||
|
inflater->shift = 0;
|
||||||
DEBUGF(fprintf(stderr, "inflatehd: huffman encoded=%d\n",
|
DEBUGF(fprintf(stderr, "inflatehd: huffman encoded=%d\n",
|
||||||
inflater->huffman_encoded != 0));
|
inflater->huffman_encoded != 0));
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
|
|
|
@ -168,6 +168,8 @@ struct nghttp2_hd_inflater {
|
||||||
/* The maximum header table size the inflater supports. This is the
|
/* The maximum header table size the inflater supports. This is the
|
||||||
same value transmitted in SETTINGS_HEADER_TABLE_SIZE */
|
same value transmitted in SETTINGS_HEADER_TABLE_SIZE */
|
||||||
size_t settings_hd_table_bufsize_max;
|
size_t settings_hd_table_bufsize_max;
|
||||||
|
/* The number of next shift to decode integer */
|
||||||
|
size_t shift;
|
||||||
nghttp2_hd_opcode opcode;
|
nghttp2_hd_opcode opcode;
|
||||||
nghttp2_hd_inflate_state state;
|
nghttp2_hd_inflate_state state;
|
||||||
/* nonzero if string is huffman encoded */
|
/* nonzero if string is huffman encoded */
|
||||||
|
|
Loading…
Reference in New Issue