You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
264 lines
9.8 KiB
264 lines
9.8 KiB
OpenPKG-SA-2005.008 and CAN-2005-1260, |
|
Infinite loop in decompression of specially crafted bzip2 archives. |
|
Parts of following patch taken from Ubuntu (backport from bzip2 1.0.3): |
|
http://security.ubuntu.com/ubuntu/pool/main/b/bzip2/bzip2_1.0.2-2ubuntu0.1.diff.gz |
|
|
|
Index: src/bzip2/bzlib.c |
|
diff -Nau src/bzip2/bzlib.c.orig src/bzip2/bzlib.c |
|
--- src/bzip2/bzlib.c.orig 2004-12-19 14:51:31 +0100 |
|
+++ src/bzip2/bzlib.c 2005-06-08 10:46:17 +0200 |
|
@@ -575,8 +575,11 @@ |
|
|
|
|
|
/*---------------------------------------------------*/ |
|
+/* Return True if data corruption is discovered. |
|
+ Returns False if there is no problem. |
|
+*/ |
|
static |
|
-void unRLE_obuf_to_output_FAST ( DState* s ) |
|
+Bool unRLE_obuf_to_output_FAST ( DState* s ) |
|
{ |
|
UChar k1; |
|
|
|
@@ -585,7 +588,7 @@ |
|
while (True) { |
|
/* try to finish existing run */ |
|
while (True) { |
|
- if (s->strm->avail_out == 0) return; |
|
+ if (s->strm->avail_out == 0) return False; |
|
if (s->state_out_len == 0) break; |
|
*( (UChar*)(s->strm->next_out) ) = s->state_out_ch; |
|
BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); |
|
@@ -597,8 +600,11 @@ |
|
} |
|
|
|
/* can a new run be started? */ |
|
- if (s->nblock_used == s->save_nblock+1) return; |
|
+ if (s->nblock_used == s->save_nblock+1) return False; |
|
|
|
+ /* Only caused by corrupt data stream? */ |
|
+ if (s->nblock_used > s->save_nblock+1) |
|
+ return True; |
|
|
|
s->state_out_len = 1; |
|
s->state_out_ch = s->k0; |
|
@@ -668,6 +674,10 @@ |
|
cs_avail_out--; |
|
} |
|
} |
|
+ /* Only caused by corrupt data stream? */ |
|
+ if (c_nblock_used > s_save_nblockPP) |
|
+ return True; |
|
+ |
|
/* can a new run be started? */ |
|
if (c_nblock_used == s_save_nblockPP) { |
|
c_state_out_len = 0; goto return_notr; |
|
@@ -713,6 +723,7 @@ |
|
s->strm->avail_out = cs_avail_out; |
|
/* end save */ |
|
} |
|
+ return False; |
|
} |
|
|
|
|
|
@@ -733,8 +744,11 @@ |
|
|
|
|
|
/*---------------------------------------------------*/ |
|
+/* Return True if data corruption is discovered. |
|
+ Returns False if there is no problem. |
|
+*/ |
|
static |
|
-void unRLE_obuf_to_output_SMALL ( DState* s ) |
|
+Bool unRLE_obuf_to_output_SMALL ( DState* s ) |
|
{ |
|
UChar k1; |
|
|
|
@@ -743,7 +757,7 @@ |
|
while (True) { |
|
/* try to finish existing run */ |
|
while (True) { |
|
- if (s->strm->avail_out == 0) return; |
|
+ if (s->strm->avail_out == 0) return False; |
|
if (s->state_out_len == 0) break; |
|
*( (UChar*)(s->strm->next_out) ) = s->state_out_ch; |
|
BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); |
|
@@ -755,8 +769,11 @@ |
|
} |
|
|
|
/* can a new run be started? */ |
|
- if (s->nblock_used == s->save_nblock+1) return; |
|
- |
|
+ if (s->nblock_used == s->save_nblock+1) return False; |
|
+ |
|
+ /* Only caused by corrupt data stream? */ |
|
+ if (s->nblock_used > s->save_nblock+1) |
|
+ return True; |
|
|
|
s->state_out_len = 1; |
|
s->state_out_ch = s->k0; |
|
@@ -789,7 +806,7 @@ |
|
while (True) { |
|
/* try to finish existing run */ |
|
while (True) { |
|
- if (s->strm->avail_out == 0) return; |
|
+ if (s->strm->avail_out == 0) return False; |
|
if (s->state_out_len == 0) break; |
|
*( (UChar*)(s->strm->next_out) ) = s->state_out_ch; |
|
BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); |
|
@@ -801,7 +818,11 @@ |
|
} |
|
|
|
/* can a new run be started? */ |
|
- if (s->nblock_used == s->save_nblock+1) return; |
|
+ if (s->nblock_used == s->save_nblock+1) return False; |
|
+ |
|
+ /* Only caused by corrupt data stream? */ |
|
+ if (s->nblock_used > s->save_nblock+1) |
|
+ return True; |
|
|
|
s->state_out_len = 1; |
|
s->state_out_ch = s->k0; |
|
@@ -831,6 +852,7 @@ |
|
/*---------------------------------------------------*/ |
|
int BZ_API(BZ2_bzDecompress) ( bz_stream *strm ) |
|
{ |
|
+ Bool corrupt; |
|
DState* s; |
|
if (strm == NULL) return BZ_PARAM_ERROR; |
|
s = strm->state; |
|
@@ -841,12 +863,13 @@ |
|
if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; |
|
if (s->state == BZ_X_OUTPUT) { |
|
if (s->smallDecompress) |
|
- unRLE_obuf_to_output_SMALL ( s ); else |
|
- unRLE_obuf_to_output_FAST ( s ); |
|
+ corrupt = unRLE_obuf_to_output_SMALL ( s ); else |
|
+ corrupt = unRLE_obuf_to_output_FAST ( s ); |
|
+ if (corrupt) return BZ_DATA_ERROR; |
|
if (s->nblock_used == s->save_nblock+1 && s->state_out_len == 0) { |
|
BZ_FINALISE_CRC ( s->calculatedBlockCRC ); |
|
if (s->verbosity >= 3) |
|
- VPrintf2 ( " {0x%x, 0x%x}", s->storedBlockCRC, |
|
+ VPrintf2 ( " {0x%08x, 0x%08x}", s->storedBlockCRC, |
|
s->calculatedBlockCRC ); |
|
if (s->verbosity >= 2) VPrintf0 ( "]" ); |
|
if (s->calculatedBlockCRC != s->storedBlockCRC) |
|
@@ -864,7 +887,7 @@ |
|
Int32 r = BZ2_decompress ( s ); |
|
if (r == BZ_STREAM_END) { |
|
if (s->verbosity >= 3) |
|
- VPrintf2 ( "\n combined CRCs: stored = 0x%x, computed = 0x%x", |
|
+ VPrintf2 ( "\n combined CRCs: stored = 0x%08x, computed = 0x%08x", |
|
s->storedCombinedCRC, s->calculatedCombinedCRC ); |
|
if (s->calculatedCombinedCRC != s->storedCombinedCRC) |
|
return BZ_DATA_ERROR; |
|
Index: src/bzip2/compress.c |
|
diff -Nau src/bzip2/compress.c.orig src/bzip2/compress.c |
|
--- src/bzip2/compress.c.orig 2004-12-19 14:51:31 +0100 |
|
+++ src/bzip2/compress.c 2005-06-08 10:46:17 +0200 |
|
@@ -489,9 +489,11 @@ |
|
/*-- |
|
Recompute the tables based on the accumulated frequencies. |
|
--*/ |
|
+ /* maxLen was changed from 20 to 17 in bzip2-1.0.3. See |
|
+ comment in huffman.c for details. */ |
|
for (t = 0; t < nGroups; t++) |
|
BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]), |
|
- alphaSize, 20 ); |
|
+ alphaSize, 17 /*20*/ ); |
|
} |
|
|
|
|
|
@@ -528,7 +530,7 @@ |
|
if (s->len[t][i] > maxLen) maxLen = s->len[t][i]; |
|
if (s->len[t][i] < minLen) minLen = s->len[t][i]; |
|
} |
|
- AssertH ( !(maxLen > 20), 3004 ); |
|
+ AssertH ( !(maxLen > 17 /*20*/ ), 3004 ); |
|
AssertH ( !(minLen < 1), 3005 ); |
|
BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]), |
|
minLen, maxLen, alphaSize ); |
|
@@ -652,8 +654,8 @@ |
|
if (s->blockNo > 1) s->numZ = 0; |
|
|
|
if (s->verbosity >= 2) |
|
- VPrintf4( " block %d: crc = 0x%8x, " |
|
- "combined CRC = 0x%8x, size = %d\n", |
|
+ VPrintf4( " block %d: crc = 0x%08x, " |
|
+ "combined CRC = 0x%08x, size = %d\n", |
|
s->blockNo, s->blockCRC, s->combinedCRC, s->nblock ); |
|
|
|
BZ2_blockSort ( s ); |
|
@@ -704,7 +706,7 @@ |
|
bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 ); |
|
bsPutUInt32 ( s, s->combinedCRC ); |
|
if (s->verbosity >= 2) |
|
- VPrintf1( " final combined CRC = 0x%x\n ", s->combinedCRC ); |
|
+ VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC ); |
|
bsFinishWrite ( s ); |
|
} |
|
} |
|
Index: src/bzip2/decompress.c |
|
diff -Nau src/bzip2/decompress.c.orig src/bzip2/decompress.c |
|
--- src/bzip2/decompress.c.orig 2004-12-19 14:51:31 +0100 |
|
+++ src/bzip2/decompress.c 2005-06-08 10:46:17 +0200 |
|
@@ -524,17 +524,23 @@ |
|
if (s->origPtr < 0 || s->origPtr >= nblock) |
|
RETURN(BZ_DATA_ERROR); |
|
|
|
+ /*-- Set up cftab to facilitate generation of T^(-1) --*/ |
|
+ s->cftab[0] = 0; |
|
+ for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1]; |
|
+ for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1]; |
|
+ for (i = 0; i <= 256; i++) { |
|
+ if (s->cftab[i] < 0 || s->cftab[i] > nblock) { |
|
+ /* s->cftab[i] can legitimately be == nblock */ |
|
+ RETURN(BZ_DATA_ERROR); |
|
+ } |
|
+ } |
|
+ |
|
s->state_out_len = 0; |
|
s->state_out_ch = 0; |
|
BZ_INITIALISE_CRC ( s->calculatedBlockCRC ); |
|
s->state = BZ_X_OUTPUT; |
|
if (s->verbosity >= 2) VPrintf0 ( "rt+rld" ); |
|
|
|
- /*-- Set up cftab to facilitate generation of T^(-1) --*/ |
|
- s->cftab[0] = 0; |
|
- for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1]; |
|
- for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1]; |
|
- |
|
if (s->smallDecompress) { |
|
|
|
/*-- Make a copy of cftab, used in generation of T --*/ |
|
Index: src/bzip2/huffman.c |
|
diff -Nau src/bzip2/huffman.c.orig analog-6.0/src/bzip2/huffman.c |
|
--- src/bzip2/huffman.c.orig 2004-12-19 14:51:31 +0100 |
|
+++ src/bzip2/huffman.c 2005-06-08 10:46:17 +0200 |
|
@@ -162,7 +162,24 @@ |
|
|
|
if (! tooLong) break; |
|
|
|
- for (i = 1; i < alphaSize; i++) { |
|
+ /* 17 Oct 04: keep-going condition for the following loop used |
|
+ to be 'i < alphaSize', which missed the last element, |
|
+ theoretically leading to the possibility of the compressor |
|
+ looping. However, this count-scaling step is only needed if |
|
+ one of the generated Huffman code words is longer than |
|
+ maxLen, which up to and including version 1.0.2 was 20 bits, |
|
+ which is extremely unlikely. In version 1.0.3 maxLen was |
|
+ changed to 17 bits, which has minimal effect on compression |
|
+ ratio, but does mean this scaling step is used from time to |
|
+ time, enough to verify that it works. |
|
+ |
|
+ This means that bzip2-1.0.3 and later will only produce |
|
+ Huffman codes with a maximum length of 17 bits. However, in |
|
+ order to preserve backwards compatibility with bitstreams |
|
+ produced by versions pre-1.0.3, the decompressor must still |
|
+ handle lengths of up to 20. */ |
|
+ |
|
+ for (i = 1; i <= alphaSize; i++) { |
|
j = weight[i] >> 8; |
|
j = 1 + (j / 2); |
|
weight[i] = j << 8;
|
|
|