diff options
author | bz <bz@FreeBSD.org> | 2011-09-28 08:47:17 +0000 |
---|---|---|
committer | bz <bz@FreeBSD.org> | 2011-09-28 08:47:17 +0000 |
commit | 2e8e044c2fd777a22fe0e18a64666670c4b72dd7 (patch) | |
tree | 6b2a5e897537e8defdf4089f141f835461cd9343 /usr.bin/compress | |
parent | 38b4a9842482e6817e8229e2fb567a4431b1924b (diff) | |
download | FreeBSD-src-2e8e044c2fd777a22fe0e18a64666670c4b72dd7.zip FreeBSD-src-2e8e044c2fd777a22fe0e18a64666670c4b72dd7.tar.gz |
Fix handling of corrupt compress(1)ed data. [11:04]
Add missing length checks on unix socket addresses. [11:05]
Approved by: so (cperciva)
Approved by: re (kensmith)
Security: FreeBSD-SA-11:04.compress
Security: CVE-2011-2895 [11:04]
Security: FreeBSD-SA-11:05.unix
Diffstat (limited to 'usr.bin/compress')
-rw-r--r-- | usr.bin/compress/zopen.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/usr.bin/compress/zopen.c b/usr.bin/compress/zopen.c index a729e13..8ae3d7d 100644 --- a/usr.bin/compress/zopen.c +++ b/usr.bin/compress/zopen.c @@ -486,7 +486,7 @@ zread(void *cookie, char *rbp, int num) block_compress = maxbits & BLOCK_MASK; maxbits &= BIT_MASK; maxmaxcode = 1L << maxbits; - if (maxbits > BITS) { + if (maxbits > BITS || maxbits < 12) { errno = EFTYPE; return (-1); } @@ -513,17 +513,28 @@ zread(void *cookie, char *rbp, int num) for (code = 255; code >= 0; code--) tab_prefixof(code) = 0; clear_flg = 1; - free_ent = FIRST - 1; - if ((code = getcode(zs)) == -1) /* O, untimely death! */ - break; + free_ent = FIRST; + oldcode = -1; + continue; } incode = code; - /* Special case for KwKwK string. */ + /* Special case for kWkWk string. */ if (code >= free_ent) { + if (code > free_ent || oldcode == -1) { + /* Bad stream. */ + errno = EINVAL; + return (-1); + } *stackp++ = finchar; code = oldcode; } + /* + * The above condition ensures that code < free_ent. + * The construction of tab_prefixof in turn guarantees that + * each iteration decreases code and therefore stack usage is + * bound by 1 << BITS - 256. + */ /* Generate output characters in reverse order. */ while (code >= 256) { @@ -540,7 +551,7 @@ middle: do { } while (stackp > de_stack); /* Generate the new entry. */ - if ((code = free_ent) < maxmaxcode) { + if ((code = free_ent) < maxmaxcode && oldcode != -1) { tab_prefixof(code) = (u_short) oldcode; tab_suffixof(code) = finchar; free_ent = code + 1; |