From caf5ee0dd9250a4ca913691bcdc247f8fe814e22 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 26 Oct 2019 20:04:34 +0200 Subject: gunzip: fix incorrect decoding of "fixed" inflate blocks function old new delta huft_build 1008 1022 +14 inflate_block 1253 1256 +3 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 17/0) Total: 17 bytes Signed-off-by: Denys Vlasenko --- archival/libarchive/decompress_gunzip.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'archival') diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index 0f8173d0a..03049cc9b 100644 --- a/archival/libarchive/decompress_gunzip.c +++ b/archival/libarchive/decompress_gunzip.c @@ -280,11 +280,17 @@ static unsigned fill_bitbuffer(STATE_PARAM unsigned bitbuffer, unsigned *current * b: code lengths in bits (all assumed <= BMAX) * n: number of codes (assumed <= N_MAX) * s: number of simple-valued codes (0..s-1) - * d: list of base values for non-simple codes - * e: list of extra bits for non-simple codes + * cp_ext->cp,ext: list of base values/extra bits for non-simple codes * m: maximum lookup bits, returns actual * result: starting table + * + * On error, returns a value with lowest-bit set on error. + * It can be just the value of 0x1, + * or a valid pointer to a Huffman table, ORed with 0x1 if incompete table + * is given: "fixed inflate" decoder feeds us such data. */ +#define BAD_HUFT(p) ((uintptr_t)(p) & 1) +#define ERR_RET ((huft_t*)(uintptr_t)1) static huft_t* huft_build(const unsigned *b, const unsigned n, const unsigned s, const struct cp_ext *cp_ext, unsigned *m) @@ -347,11 +353,11 @@ static huft_t* huft_build(const unsigned *b, const unsigned n, for (y = 1 << j; j < i; j++, y <<= 1) { y -= c[j]; if (y < 0) - return NULL; /* bad input: more codes than bits */ + return ERR_RET; /* bad input: more codes than bits */ } y -= c[i]; if (y < 0) - return NULL; + return ERR_RET; c[i] += y; /* Generate starting offsets into the value table for each length */ @@ -378,7 +384,7 @@ static huft_t* huft_build(const unsigned *b, const unsigned n, } while (++i < n); /* Generate the Huffman codes and for each, make the table entries */ - result = NULL; + result = ERR_RET; t = &result; x[0] = i = 0; /* first Huffman code is zero */ p = v; /* grab values in bit order */ @@ -472,7 +478,8 @@ static huft_t* huft_build(const unsigned *b, const unsigned n, *m = ws[1]; if (y != 0 && g != 1) /* we were given an incomplete table */ - return NULL; + /* return "result" ORed with 1 */ + return (void*)((uintptr_t)result | 1); return result; } @@ -776,13 +783,16 @@ static int inflate_block(STATE_PARAM smallint *e) ll[i] = 8; bl = 7; inflate_codes_tl = huft_build(ll, 288, 257, &lit, &bl); - /* huft_build() never returns error here - we use known data */ + /* ^^^ never returns error here - we use known data */ /* set up distance table */ for (i = 0; i < 30; i++) /* make an incomplete code set */ ll[i] = 5; bd = 5; inflate_codes_td = huft_build(ll, 30, 0, &dist, &bd); + /* ^^^ does return error here! (lsb bit is set) - we gave it incomplete code set */ + /* clearing error bit: */ + inflate_codes_td = (void*)((uintptr_t)inflate_codes_td & ~(uintptr_t)1); /* set up data for inflate_codes() */ inflate_codes_setup(PASS_STATE bl, bd); @@ -849,7 +859,7 @@ static int inflate_block(STATE_PARAM smallint *e) /* build decoding table for trees - single level, 7 bit lookup */ bl = 7; inflate_codes_tl = huft_build(ll, 19, 19, NULL, &bl); - if (!inflate_codes_tl) { + if (BAD_HUFT(inflate_codes_tl)) { abort_unzip(PASS_STATE_ONLY); /* incomplete code set */ } @@ -914,12 +924,12 @@ static int inflate_block(STATE_PARAM smallint *e) /* build the decoding tables for literal/length and distance codes */ bl = lbits; inflate_codes_tl = huft_build(ll, nl, 257, &lit, &bl); - if (!inflate_codes_tl) { + if (BAD_HUFT(inflate_codes_tl)) { abort_unzip(PASS_STATE_ONLY); } bd = dbits; inflate_codes_td = huft_build(ll + nl, nd, 0, &dist, &bd); - if (!inflate_codes_td) { + if (BAD_HUFT(inflate_codes_td)) { abort_unzip(PASS_STATE_ONLY); } -- cgit v1.2.3