diff --git a/nrs/ext/bzlib/bzlib.c b/nrs/ext/bzlib/bzlib.c index fef83b2..1b37d7a 100644 --- a/nrs/ext/bzlib/bzlib.c +++ b/nrs/ext/bzlib/bzlib.c @@ -115,7 +115,7 @@ Int32 NSISCALL BZ2_indexIntoF ( Int32 indx, Int32 *cftab ) static -void NSISCALL unRLE_obuf_to_output_SMALL ( DState* s ) +Bool NSISCALL unRLE_obuf_to_output_SMALL ( DState* s ) { UChar k1; while (True) { @@ -130,7 +130,11 @@ void NSISCALL unRLE_obuf_to_output_SMALL ( DState* s ) } /* 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; @@ -154,7 +158,7 @@ void NSISCALL unRLE_obuf_to_output_SMALL ( DState* s ) } } #else//!small, fast -static void NSISCALL unRLE_obuf_to_output_FAST ( DState* s ) +static Bool NSISCALL unRLE_obuf_to_output_FAST ( DState* s ) { UChar k1; @@ -195,6 +199,10 @@ static void NSISCALL unRLE_obuf_to_output_FAST ( DState* s ) 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; @@ -231,6 +239,7 @@ static void NSISCALL unRLE_obuf_to_output_FAST ( DState* s ) s->next_out = (unsigned char*) cs_next_out; s->avail_out = cs_avail_out; /* end save */ + return False; } #endif @@ -239,14 +248,16 @@ static void NSISCALL unRLE_obuf_to_output_FAST ( DState* s ) /*---------------------------------------------------*/ int NSISCALL BZ2_bzDecompress( DState *s ) { + Bool corrupt; while (True) { if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR; if (s->state == BZ_X_OUTPUT) { #ifdef NSIS_COMPRESS_BZIP2_SMALLMODE - unRLE_obuf_to_output_SMALL ( s ); + corrupt = unRLE_obuf_to_output_SMALL ( s ); #else - unRLE_obuf_to_output_FAST ( s ); + corrupt = unRLE_obuf_to_output_FAST ( s ); #endif + if (corrupt) return BZ_DATA_ERROR; if (s->nblock_used == s->save.nblock+1 && s->state_out_len == 0) { s->state = BZ_X_BLKHDR_1; } else { diff --git a/nrs/ext/bzlib/bzlib.h b/nrs/ext/bzlib/bzlib.h index 69aeaad..23cb394 100644 --- a/nrs/ext/bzlib/bzlib.h +++ b/nrs/ext/bzlib/bzlib.h @@ -266,11 +266,13 @@ typedef struct { /*-- Macros for decompression. --*/ #define BZ_GET_FAST(cccc) \ + if (s->tPos >= (UInt32)100000 * NSIS_COMPRESS_BZIP2_LEVEL) return True; \ s->tPos = s->tt[s->tPos]; \ cccc = (UChar)(s->tPos & 0xff); \ s->tPos >>= 8; #define BZ_GET_FAST_C(cccc) \ + if (c_tPos >= (UInt32)100000 * NSIS_COMPRESS_BZIP2_LEVEL) return True; \ c_tPos = c_tt[c_tPos]; \ cccc = (UChar)(c_tPos & 0xff); \ c_tPos >>= 8; @@ -296,6 +298,7 @@ typedef struct { (((UInt32)s->ll16[i]) | (GET_LL4(i) << 16)) #define BZ_GET_SMALL(cccc) \ + if (s->tPos >= (UInt32)100000 * NSIS_COMPRESS_BZIP2_LEVEL) return True; \ cccc = BZ2_indexIntoF ( s->tPos, s->cftab ); \ s->tPos = GET_LL(s->tPos); diff --git a/nrs/ext/bzlib/decompress.c b/nrs/ext/bzlib/decompress.c index 33c890a..2a942a6 100644 --- a/nrs/ext/bzlib/decompress.c +++ b/nrs/ext/bzlib/decompress.c @@ -1,14 +1,14 @@ /* * This file is a part of the bzip2 compression module for NSIS. - * + * * Copyright and license information can be found below. * Modifications Copyright (C) 1999-2015 Nullsoft and Contributors - * + * * The original zlib source code is available at * http://www.bzip.org/ - * + * * This modification is not compatible with the original bzip2. - * + * * This software is provided 'as-is', without any express or implied * warranty. * @@ -252,8 +252,14 @@ Int32 NSISCALL BZ2_decompress ( DState* s ) j++; if (j >= nGroups) RETURN(BZ_DATA_ERROR); } - s->selectorMtf[i] = j; + /* Having more than BZ_MAX_SELECTORS doesn't make much sense + since they will never be used, but some implementations might + "round up" the number of selectors, so just ignore those. */ + if (i < BZ_MAX_SELECTORS) + s->selectorMtf[i] = j; } + if (nSelectors > BZ_MAX_SELECTORS) + nSelectors = BZ_MAX_SELECTORS; /*--- Undo the MTF values for the selectors. ---*/ { @@ -337,6 +343,13 @@ Int32 NSISCALL BZ2_decompress ( DState* s ) N = 1; while (nextSym == BZ_RUNA || nextSym == BZ_RUNB) { + /* Check that N doesn't get too big, so that es doesn't + go negative. The maximum value that can be + RUNA/RUNB encoded is equal to the block size (post + the initial RLE), viz, 900k, so bounding N at 2 + million should guard against overflow without + rejecting any legitimate inputs. */ + if (N >= 2*1024*1024) RETURN(BZ_DATA_ERROR); if (nextSym == BZ_RUNA) es += N; N = N << 1; if (nextSym == BZ_RUNB) es += N; @@ -446,10 +459,28 @@ Int32 NSISCALL BZ2_decompress ( DState* s ) s->state_out_ch = 0; s->state = BZ_X_OUTPUT; - /*-- Set up cftab to facilitate generation of T^(-1) --*/ + /* Check: unzftab entries in range. */ + for (i = 0; i <= 255; i++) { + if (s->unzftab[i] < 0 || s->unzftab[i] > nblock) + RETURN(BZ_DATA_ERROR); + } + /* Actually generate cftab. */ s->cftab[0] = 0; + /* Actually generate cftab. */ for (i = 1; i <= 256; i++) s->cftab[i] = s->unzftab[i-1]+s->cftab[i-1]; -// for (i = 1; i <= 256; i++) s->cftab[i] += s->cftab[i-1]; + /* Check: cftab entries in range. */ + 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); + } + } + /* Check: cftab entries non-descending. */ + for (i = 1; i <= 256; i++) { + if (s->cftab[i-1] > s->cftab[i]) { + RETURN(BZ_DATA_ERROR); + } + } #ifdef NSIS_COMPRESS_BZIP2_SMALLMODE {