diff --git a/proxy/http2/HPACK.cc b/proxy/http2/HPACK.cc index 2f90f1686a3..0576f1c281f 100644 --- a/proxy/http2/HPACK.cc +++ b/proxy/http2/HPACK.cc @@ -708,7 +708,7 @@ decode_string(Arena &arena, char **str, uint32_t &str_length, const uint8_t *buf *str = arena.str_alloc(encoded_string_len * 2); len = huffman_decode(*str, p, encoded_string_len); - if (len == HPACK_ERROR_COMPRESSION_ERROR) { + if (len < 0) { return HPACK_ERROR_COMPRESSION_ERROR; } str_length = len; diff --git a/proxy/http2/HuffmanCodec.cc b/proxy/http2/HuffmanCodec.cc index 45ec21441a7..34ec166a7d8 100644 --- a/proxy/http2/HuffmanCodec.cc +++ b/proxy/http2/HuffmanCodec.cc @@ -151,21 +151,26 @@ hpack_huffman_fin() int64_t huffman_decode(char *dst_start, const uint8_t *src, uint32_t src_len) { - char *dst_end = dst_start; - uint8_t shift = 7; - Node *current = HUFFMAN_TREE_ROOT; + char *dst_end = dst_start; + uint8_t shift = 7; + Node *current = HUFFMAN_TREE_ROOT; + int byte_boundary_crossed = 0; + bool includes_zero = false; while (src_len) { if (*src & (1 << shift)) { current = current->right; } else { - current = current->left; + current = current->left; + includes_zero = true; } if (current->leaf_node == true) { *dst_end = current->ascii_code; ++dst_end; - current = HUFFMAN_TREE_ROOT; + current = HUFFMAN_TREE_ROOT; + byte_boundary_crossed = 0; + includes_zero = false; } if (shift) { --shift; @@ -173,7 +178,17 @@ huffman_decode(char *dst_start, const uint8_t *src, uint32_t src_len) shift = 7; ++src; --src_len; + ++byte_boundary_crossed; } + if (byte_boundary_crossed > 3) { + return -1; + } + } + if (byte_boundary_crossed > 1) { + return -1; + } + if (includes_zero) { + return -1; } return dst_end - dst_start;