Commit ab49402d authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[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.
parent 0a33358c
...@@ -221,7 +221,7 @@ STATIC const ush mask_bits[] = { ...@@ -221,7 +221,7 @@ STATIC const ush mask_bits[] = {
0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff 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 NEEDBITS(n) {while(k<(n)){b|=((ulg)NEXTBYTE())<<k;k+=8;}}
#define DUMPBITS(n) {b>>=(n);k-=(n);} #define DUMPBITS(n) {b>>=(n);k-=(n);}
...@@ -620,6 +620,9 @@ STATIC int inflate_codes( ...@@ -620,6 +620,9 @@ STATIC int inflate_codes(
/* done */ /* done */
return 0; return 0;
underrun:
return 4; /* Input underrun */
} }
...@@ -676,6 +679,9 @@ DEBG("<stor"); ...@@ -676,6 +679,9 @@ DEBG("<stor");
DEBG(">"); DEBG(">");
return 0; return 0;
underrun:
return 4; /* Input underrun */
} }
...@@ -908,6 +914,9 @@ DEBG("dyn7 "); ...@@ -908,6 +914,9 @@ DEBG("dyn7 ");
DEBG(">"); DEBG(">");
return 0; return 0;
underrun:
return 4; /* Input underrun */
} }
...@@ -956,6 +965,9 @@ STATIC int inflate_block( ...@@ -956,6 +965,9 @@ STATIC int inflate_block(
/* bad block type */ /* bad block type */
return 2; return 2;
underrun:
return 4; /* Input underrun */
} }
...@@ -1079,9 +1091,9 @@ static int gunzip(void) ...@@ -1079,9 +1091,9 @@ static int gunzip(void)
ulg orig_len = 0; /* original uncompressed length */ ulg orig_len = 0; /* original uncompressed length */
int res; int res;
magic[0] = (unsigned char)get_byte(); magic[0] = NEXTBYTE();
magic[1] = (unsigned char)get_byte(); magic[1] = NEXTBYTE();
method = (unsigned char)get_byte(); method = NEXTBYTE();
if (magic[0] != 037 || if (magic[0] != 037 ||
((magic[1] != 0213) && (magic[1] != 0236))) { ((magic[1] != 0213) && (magic[1] != 0236))) {
...@@ -1108,29 +1120,29 @@ static int gunzip(void) ...@@ -1108,29 +1120,29 @@ static int gunzip(void)
error("Input has invalid flags"); error("Input has invalid flags");
return -1; return -1;
} }
(ulg)get_byte(); /* Get timestamp */ NEXTBYTE(); /* Get timestamp */
((ulg)get_byte()) << 8; NEXTBYTE();
((ulg)get_byte()) << 16; NEXTBYTE();
((ulg)get_byte()) << 24; NEXTBYTE();
(void)get_byte(); /* Ignore extra flags for the moment */ (void)NEXTBYTE(); /* Ignore extra flags for the moment */
(void)get_byte(); /* Ignore OS type for the moment */ (void)NEXTBYTE(); /* Ignore OS type for the moment */
if ((flags & EXTRA_FIELD) != 0) { if ((flags & EXTRA_FIELD) != 0) {
unsigned len = (unsigned)get_byte(); unsigned len = (unsigned)NEXTBYTE();
len |= ((unsigned)get_byte())<<8; len |= ((unsigned)NEXTBYTE())<<8;
while (len--) (void)get_byte(); while (len--) (void)NEXTBYTE();
} }
/* Get original file name if it was truncated */ /* Get original file name if it was truncated */
if ((flags & ORIG_NAME) != 0) { if ((flags & ORIG_NAME) != 0) {
/* Discard the old name */ /* Discard the old name */
while (get_byte() != 0) /* null */ ; while (NEXTBYTE() != 0) /* null */ ;
} }
/* Discard file comment if any */ /* Discard file comment if any */
if ((flags & COMMENT) != 0) { if ((flags & COMMENT) != 0) {
while (get_byte() != 0) /* null */ ; while (NEXTBYTE() != 0) /* null */ ;
} }
/* Decompress */ /* Decompress */
...@@ -1147,6 +1159,9 @@ static int gunzip(void) ...@@ -1147,6 +1159,9 @@ static int gunzip(void)
case 3: case 3:
error("out of memory"); error("out of memory");
break; break;
case 4:
error("out of input data");
break;
default: default:
error("invalid compressed format (other)"); error("invalid compressed format (other)");
} }
...@@ -1157,15 +1172,15 @@ static int gunzip(void) ...@@ -1157,15 +1172,15 @@ static int gunzip(void)
/* crc32 (see algorithm.doc) /* crc32 (see algorithm.doc)
* uncompressed input size modulo 2^32 * uncompressed input size modulo 2^32
*/ */
orig_crc = (ulg) get_byte(); orig_crc = (ulg) NEXTBYTE();
orig_crc |= (ulg) get_byte() << 8; orig_crc |= (ulg) NEXTBYTE() << 8;
orig_crc |= (ulg) get_byte() << 16; orig_crc |= (ulg) NEXTBYTE() << 16;
orig_crc |= (ulg) get_byte() << 24; orig_crc |= (ulg) NEXTBYTE() << 24;
orig_len = (ulg) get_byte(); orig_len = (ulg) NEXTBYTE();
orig_len |= (ulg) get_byte() << 8; orig_len |= (ulg) NEXTBYTE() << 8;
orig_len |= (ulg) get_byte() << 16; orig_len |= (ulg) NEXTBYTE() << 16;
orig_len |= (ulg) get_byte() << 24; orig_len |= (ulg) NEXTBYTE() << 24;
/* Validate decompression */ /* Validate decompression */
if (orig_crc != CRC_VALUE) { if (orig_crc != CRC_VALUE) {
...@@ -1177,6 +1192,10 @@ static int gunzip(void) ...@@ -1177,6 +1192,10 @@ static int gunzip(void)
return -1; return -1;
} }
return 0; return 0;
underrun: /* NEXTBYTE() goto's here if needed */
error("out of input data");
return -1;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment