BUG/CRITICAL: hpack: fix improper sign check on the header index value
Tim Düsterhus found using afl-fuzz that some parts of the HPACK decoder
use incorrect bounds checking which do not catch negative values after
a type cast. The first culprit is hpack_valid_idx() which takes a signed
int and is fed with an unsigned one, but a few others are affected as
well due to being designed to work with an uint16_t as in the table
header, thus not being able to detect the high offset bits, though they
are not exposed if hpack_valid_idx() is fixed.
The impact is that the HPACK decoder can be crashed by an out-of-bounds
read. The only work-around without this patch is to disable H2 in the
configuration.
CVE-2018-14645 was assigned to this bug.
This patch addresses all of these issues at once. It must be backported
to 1.8.
diff --git a/include/common/hpack-tbl.h b/include/common/hpack-tbl.h
index ffa866b..385f386 100644
--- a/include/common/hpack-tbl.h
+++ b/include/common/hpack-tbl.h
@@ -155,7 +155,7 @@
}
/* returns non-zero if <idx> is valid for table <dht> */
-static inline int hpack_valid_idx(const struct hpack_dht *dht, uint16_t idx)
+static inline int hpack_valid_idx(const struct hpack_dht *dht, uint32_t idx)
{
return idx < dht->used + HPACK_SHT_SIZE;
}
@@ -181,7 +181,7 @@
}
/* takes an idx, returns the associated name */
-static inline struct ist hpack_idx_to_name(const struct hpack_dht *dht, int idx)
+static inline struct ist hpack_idx_to_name(const struct hpack_dht *dht, uint32_t idx)
{
const struct hpack_dte *dte;
@@ -196,7 +196,7 @@
}
/* takes an idx, returns the associated value */
-static inline struct ist hpack_idx_to_value(const struct hpack_dht *dht, int idx)
+static inline struct ist hpack_idx_to_value(const struct hpack_dht *dht, uint32_t idx)
{
const struct hpack_dte *dte;
diff --git a/src/hpack-dec.c b/src/hpack-dec.c
index 16a722f..148a9a2 100644
--- a/src/hpack-dec.c
+++ b/src/hpack-dec.c
@@ -114,7 +114,7 @@
* allocated there. In case of allocation failure, returns a string whose
* pointer is NULL.
*/
-static inline struct ist hpack_alloc_string(struct buffer *store, int idx,
+static inline struct ist hpack_alloc_string(struct buffer *store, uint32_t idx,
struct ist in)
{
struct ist out;
diff --git a/src/hpack-tbl.c b/src/hpack-tbl.c
index 02e5a5c..24eb7c4 100644
--- a/src/hpack-tbl.c
+++ b/src/hpack-tbl.c
@@ -113,7 +113,7 @@
/* dump the whole dynamic header table */
static void hpack_dht_dump(FILE *out, const struct hpack_dht *dht)
{
- int i;
+ unsigned int i;
unsigned int slot;
char name[4096], value[4096];