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 <vda.linux@googlemail.com>
This commit is contained in:
parent
122a8cbd4a
commit
caf5ee0dd9
@ -280,11 +280,17 @@ static unsigned fill_bitbuffer(STATE_PARAM unsigned bitbuffer, unsigned *current
|
|||||||
* b: code lengths in bits (all assumed <= BMAX)
|
* b: code lengths in bits (all assumed <= BMAX)
|
||||||
* n: number of codes (assumed <= N_MAX)
|
* n: number of codes (assumed <= N_MAX)
|
||||||
* s: number of simple-valued codes (0..s-1)
|
* s: number of simple-valued codes (0..s-1)
|
||||||
* d: list of base values for non-simple codes
|
* cp_ext->cp,ext: list of base values/extra bits for non-simple codes
|
||||||
* e: list of extra bits for non-simple codes
|
|
||||||
* m: maximum lookup bits, returns actual
|
* m: maximum lookup bits, returns actual
|
||||||
* result: starting table
|
* 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,
|
static huft_t* huft_build(const unsigned *b, const unsigned n,
|
||||||
const unsigned s, const struct cp_ext *cp_ext,
|
const unsigned s, const struct cp_ext *cp_ext,
|
||||||
unsigned *m)
|
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) {
|
for (y = 1 << j; j < i; j++, y <<= 1) {
|
||||||
y -= c[j];
|
y -= c[j];
|
||||||
if (y < 0)
|
if (y < 0)
|
||||||
return NULL; /* bad input: more codes than bits */
|
return ERR_RET; /* bad input: more codes than bits */
|
||||||
}
|
}
|
||||||
y -= c[i];
|
y -= c[i];
|
||||||
if (y < 0)
|
if (y < 0)
|
||||||
return NULL;
|
return ERR_RET;
|
||||||
c[i] += y;
|
c[i] += y;
|
||||||
|
|
||||||
/* Generate starting offsets into the value table for each length */
|
/* 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);
|
} while (++i < n);
|
||||||
|
|
||||||
/* Generate the Huffman codes and for each, make the table entries */
|
/* Generate the Huffman codes and for each, make the table entries */
|
||||||
result = NULL;
|
result = ERR_RET;
|
||||||
t = &result;
|
t = &result;
|
||||||
x[0] = i = 0; /* first Huffman code is zero */
|
x[0] = i = 0; /* first Huffman code is zero */
|
||||||
p = v; /* grab values in bit order */
|
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];
|
*m = ws[1];
|
||||||
|
|
||||||
if (y != 0 && g != 1) /* we were given an incomplete table */
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
@ -776,13 +783,16 @@ static int inflate_block(STATE_PARAM smallint *e)
|
|||||||
ll[i] = 8;
|
ll[i] = 8;
|
||||||
bl = 7;
|
bl = 7;
|
||||||
inflate_codes_tl = huft_build(ll, 288, 257, &lit, &bl);
|
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 */
|
/* set up distance table */
|
||||||
for (i = 0; i < 30; i++) /* make an incomplete code set */
|
for (i = 0; i < 30; i++) /* make an incomplete code set */
|
||||||
ll[i] = 5;
|
ll[i] = 5;
|
||||||
bd = 5;
|
bd = 5;
|
||||||
inflate_codes_td = huft_build(ll, 30, 0, &dist, &bd);
|
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() */
|
/* set up data for inflate_codes() */
|
||||||
inflate_codes_setup(PASS_STATE bl, bd);
|
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 */
|
/* build decoding table for trees - single level, 7 bit lookup */
|
||||||
bl = 7;
|
bl = 7;
|
||||||
inflate_codes_tl = huft_build(ll, 19, 19, NULL, &bl);
|
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 */
|
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 */
|
/* build the decoding tables for literal/length and distance codes */
|
||||||
bl = lbits;
|
bl = lbits;
|
||||||
inflate_codes_tl = huft_build(ll, nl, 257, &lit, &bl);
|
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);
|
abort_unzip(PASS_STATE_ONLY);
|
||||||
}
|
}
|
||||||
bd = dbits;
|
bd = dbits;
|
||||||
inflate_codes_td = huft_build(ll + nl, nd, 0, &dist, &bd);
|
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);
|
abort_unzip(PASS_STATE_ONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user