diff options
author | Andrew Morton <akpm@osdl.org> | 2003-12-29 23:46:23 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@home.osdl.org> | 2003-12-29 23:46:23 -0800 |
commit | ab49402d9f61b9a2b9c483be669e81c3f89cce8b (patch) | |
tree | 254aef5bdd07486f1f4ab0969b7f4561a927fe8b /lib | |
parent | 0a33358cf289e024b7e67436f8539f1348aed238 (diff) | |
download | history-ab49402d9f61b9a2b9c483be669e81c3f89cce8b.tar.gz |
[PATCH] lib/inflate.c fix
From: "H. Peter Anvin" <hpa@zytor.com>
This patch fixes the "non-terminating inflate" problem that Russell King
complained about on LKML earlier today.
I chose to use "goto" much like zlib does, in order to not require
setjmp/longjmp inside the kernel. It's a bit ugly, but it also lets each
function chose how it needs to be terminated on error, which is a good
thing.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/inflate.c | 65 |
1 files changed, 42 insertions, 23 deletions
diff --git a/lib/inflate.c b/lib/inflate.c index 41227073442b1c..11360039187e72 100644 --- a/lib/inflate.c +++ b/lib/inflate.c @@ -221,7 +221,7 @@ STATIC const ush mask_bits[] = { 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff }; -#define NEXTBYTE() (uch)get_byte() +#define NEXTBYTE() ({ int v = get_byte(); if (v < 0) goto underrun; (uch)v; }) #define NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}} #define DUMPBITS(n) {b>>=(n);k-=(n);} @@ -620,6 +620,9 @@ STATIC int inflate_codes( /* done */ return 0; + + underrun: + return 4; /* Input underrun */ } @@ -676,6 +679,9 @@ DEBG("<stor"); DEBG(">"); return 0; + + underrun: + return 4; /* Input underrun */ } @@ -908,6 +914,9 @@ DEBG("dyn7 "); DEBG(">"); return 0; + + underrun: + return 4; /* Input underrun */ } @@ -956,6 +965,9 @@ STATIC int inflate_block( /* bad block type */ return 2; + + underrun: + return 4; /* Input underrun */ } @@ -1079,9 +1091,9 @@ static int gunzip(void) ulg orig_len = 0; /* original uncompressed length */ int res; - magic[0] = (unsigned char)get_byte(); - magic[1] = (unsigned char)get_byte(); - method = (unsigned char)get_byte(); + magic[0] = NEXTBYTE(); + magic[1] = NEXTBYTE(); + method = NEXTBYTE(); if (magic[0] != 037 || ((magic[1] != 0213) && (magic[1] != 0236))) { @@ -1108,29 +1120,29 @@ static int gunzip(void) error("Input has invalid flags"); return -1; } - (ulg)get_byte(); /* Get timestamp */ - ((ulg)get_byte()) << 8; - ((ulg)get_byte()) << 16; - ((ulg)get_byte()) << 24; + NEXTBYTE(); /* Get timestamp */ + NEXTBYTE(); + NEXTBYTE(); + NEXTBYTE(); - (void)get_byte(); /* Ignore extra flags for the moment */ - (void)get_byte(); /* Ignore OS type for the moment */ + (void)NEXTBYTE(); /* Ignore extra flags for the moment */ + (void)NEXTBYTE(); /* Ignore OS type for the moment */ if ((flags & EXTRA_FIELD) != 0) { - unsigned len = (unsigned)get_byte(); - len |= ((unsigned)get_byte())<<8; - while (len--) (void)get_byte(); + unsigned len = (unsigned)NEXTBYTE(); + len |= ((unsigned)NEXTBYTE())<<8; + while (len--) (void)NEXTBYTE(); } /* Get original file name if it was truncated */ if ((flags & ORIG_NAME) != 0) { /* Discard the old name */ - while (get_byte() != 0) /* null */ ; + while (NEXTBYTE() != 0) /* null */ ; } /* Discard file comment if any */ if ((flags & COMMENT) != 0) { - while (get_byte() != 0) /* null */ ; + while (NEXTBYTE() != 0) /* null */ ; } /* Decompress */ @@ -1147,6 +1159,9 @@ static int gunzip(void) case 3: error("out of memory"); break; + case 4: + error("out of input data"); + break; default: error("invalid compressed format (other)"); } @@ -1157,15 +1172,15 @@ static int gunzip(void) /* crc32 (see algorithm.doc) * uncompressed input size modulo 2^32 */ - orig_crc = (ulg) get_byte(); - orig_crc |= (ulg) get_byte() << 8; - orig_crc |= (ulg) get_byte() << 16; - orig_crc |= (ulg) get_byte() << 24; + orig_crc = (ulg) NEXTBYTE(); + orig_crc |= (ulg) NEXTBYTE() << 8; + orig_crc |= (ulg) NEXTBYTE() << 16; + orig_crc |= (ulg) NEXTBYTE() << 24; - orig_len = (ulg) get_byte(); - orig_len |= (ulg) get_byte() << 8; - orig_len |= (ulg) get_byte() << 16; - orig_len |= (ulg) get_byte() << 24; + orig_len = (ulg) NEXTBYTE(); + orig_len |= (ulg) NEXTBYTE() << 8; + orig_len |= (ulg) NEXTBYTE() << 16; + orig_len |= (ulg) NEXTBYTE() << 24; /* Validate decompression */ if (orig_crc != CRC_VALUE) { @@ -1177,6 +1192,10 @@ static int gunzip(void) return -1; } return 0; + + underrun: /* NEXTBYTE() goto's here if needed */ + error("out of input data"); + return -1; } |