BUG/MEDIUM: hpack: fix incorrect huffman decoding of some control chars

Commit 9f4f6b038 ("OPTIM: hpack-huff: reduce the cache footprint of the
huffman decoder") replaced the large tables with more space efficient
byte arrays, but one table, rht_bit15_11_11_4, has a 64 bytes hole in it
that wasn't materialized by filling it with zeroes to make the offsets
match, nor by adjusting the offset from the caller. This resulted in
some control chars not properly being decoded and being seen as byte 0,
and the associated messages to be rejected, as can be seen in issue #1971.

This commit fixes it by adjusting the offset used for the higher part of
the table so that we don't need to store 64 zeroes that will never be
accessed.

This needs to be backported to 2.7.

Thanks to Christopher for spotting the bug, and to Juanga Covas for
providing precious traces showing the problem.
This commit is contained in:
Willy Tarreau 2023-01-26 11:12:11 +01:00
parent b4d119f0c7
commit 094ecf19f9

View File

@ -608,8 +608,10 @@ uint8_t rht_bit15_8[256] = {
/* below two non-overlapping tables are merged in order to save on L1D:
* - bits 15-11 for values 0x00-0x1f
* - bits 11-4 for values 0x60-0xff
* Note that there's no data between 0x20 and 0x5f, the caller must
* adjust its offsets by subtracting 0x40 for values 0x60 and above.
*/
uint8_t rht_bit15_11_11_4[256] = {
uint8_t rht_bit15_11_11_4[192] = {
/* part used for bits 15-11 (0x00-0x1f) */
/* 0x00 */ 0x5c, 0x5c, 0x5c, 0x5c,
/* 0x04 */ 0xc3, 0xc3, 0xc3, 0xc3,
@ -627,7 +629,7 @@ uint8_t rht_bit15_11_11_4[256] = {
/* 0x1e */ 0xa7,
/* 0x1f */ 0xac,
/* part used for bits 11-4 for 0xf600 (0x60-0xff) */
/* part used for bits 11-4 for 0xf600 (0x60-0xff), starting @0x20 */
/* 0x60 */ 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7, 0xc7,
/* 0x68 */ 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
/* 0x70 */ 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea,
@ -816,12 +818,12 @@ int huff_dec(const uint8_t *huff, int hlen, char *out, int olen)
}
else {
/* 0xff 0xff 0xf6..0xff */
sym = code >> 4;
sym = code >> 4; /* sym = 0x60..0xff */
l = sym < 0xbc ?
sym < 0x80 ? 25 : 26 :
sym < 0xe2 ? 27 : sym < 0xff ? 28 : 30;
if (sym < 0xff)
sym = rht_bit15_11_11_4[(code >> 4) & 0xff];
sym = rht_bit15_11_11_4[((code >> 4) & 0xff) - 0x40L];
else if ((code & 0xff) == 0xf0)
sym = 10;
else if ((code & 0xff) == 0xf4)