From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Daniel Axtens Date: Thu, 21 Jan 2021 12:20:49 +1100 Subject: [PATCH] io/gzio: Catch missing values in huft_build() and bail In huft_build(), "v" is a table of values in order of bit length. The code later (when setting up table entries in "r") assumes that all elements of this array corresponding to a code are initialized and less than N_MAX. However, it doesn't enforce this. With sufficiently manipulated inputs (e.g. from fuzzing), there can be elements of "v" that are not filled. Therefore a lookup into "e" or "d" will use an uninitialized value. This can lead to an invalid/OOB read on those values, often leading to a crash. Signed-off-by: Daniel Axtens Reviewed-by: Daniel Kiper --- grub-core/io/gzio.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c index 97b34f885..f85dbae23 100644 --- a/grub-core/io/gzio.c +++ b/grub-core/io/gzio.c @@ -507,6 +507,7 @@ huft_build (unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ } /* Make a table of values in order of bit lengths */ + grub_memset (v, N_MAX, ARRAY_SIZE (v)); p = b; i = 0; do @@ -588,11 +589,18 @@ huft_build (unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ r.v.n = (ush) (*p); /* simple code is just the value */ p++; /* one compiler does not like *p++ */ } - else + else if (*p < N_MAX) { r.e = (uch) e[*p - s]; /* non-simple--look up in lists */ r.v.n = d[*p++ - s]; } + else + { + /* Detected an uninitialised value, abort. */ + if (h) + huft_free (u[0]); + return 2; + } /* fill code-like entries with r */ f = 1 << (k - w);