Fix integer decoding when it takes multiple reads

This commit is contained in:
Tatsuhiro Tsujikawa 2014-07-22 01:50:29 +09:00
parent 139c3b508a
commit 44310c6de5
2 changed files with 22 additions and 8 deletions

View File

@ -360,6 +360,7 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater)
inflater->huffman_encoded = 0;
inflater->index = 0;
inflater->left = 0;
inflater->shift = 0;
inflater->newnamelen = 0;
inflater->index_required = 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.
*
* This function returns the next byte of read byte. This function
* stores the decoded integer in |*res| if it succeed, including
* partial decoding, or stores -1 in |*res|, indicating decoding
* error.
* stores the decoded integer in |*res| and number of shift to make in
* the next decoding in |*shift_ptr| if it succeed, including partial
* 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)
{
int k = (1 << prefix) - 1, r;
int k = (1 << prefix) - 1;
ssize_t n = initial;
*shift_ptr = 0;
*final = 0;
if(n == 0) {
if((*in & k) == k) {
n = k;
@ -519,8 +524,8 @@ static uint8_t* decode_length(ssize_t *res, int *final, ssize_t initial,
return in;
}
}
for(r = 0; in != last; ++in, r += 7) {
n += (*in & 0x7f) << r;
for(; in != last; ++in, shift += 7) {
n += (*in & 0x7f) << shift;
if(n >= (1 << 16)) {
*res = -1;
return in + 1;
@ -529,6 +534,9 @@ static uint8_t* decode_length(ssize_t *res, int *final, ssize_t initial,
break;
}
}
*shift_ptr = shift;
if(in == last) {
*res = n;
return in;
@ -1350,7 +1358,8 @@ static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater,
{
uint8_t *nin;
*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) {
DEBUGF(fprintf(stderr, "inflatehd: invalid integer\n"));
return NGHTTP2_ERR_HEADER_COMP;
@ -1691,6 +1700,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
}
}
inflater->left = 0;
inflater->shift = 0;
break;
case NGHTTP2_HD_STATE_CLEAR_REFSET:
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);
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
inflater->left = 0;
inflater->shift = 0;
DEBUGF(fprintf(stderr, "inflatehd: huffman encoded=%d\n",
inflater->huffman_encoded != 0));
/* Fall through */
@ -1844,6 +1855,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
hd_inflate_set_huffman_encoded(inflater, in);
inflater->state = NGHTTP2_HD_STATE_READ_VALUELEN;
inflater->left = 0;
inflater->shift = 0;
DEBUGF(fprintf(stderr, "inflatehd: huffman encoded=%d\n",
inflater->huffman_encoded != 0));
/* Fall through */

View File

@ -168,6 +168,8 @@ struct nghttp2_hd_inflater {
/* 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;
/* The number of next shift to decode integer */
size_t shift;
nghttp2_hd_opcode opcode;
nghttp2_hd_inflate_state state;
/* nonzero if string is huffman encoded */