libclamav/nsis/bzlib.c
faaf436a
 
 /*-------------------------------------------------------------*/
 /*--- Library top-level functions.                          ---*/
 /*---                                               bzlib.c ---*/
 /*-------------------------------------------------------------*/
 
 /* ------------------------------------------------------------------
    This file is part of bzip2/libbzip2, a program and library for
    lossless, block-sorting data compression.
 
    bzip2/libbzip2 version 1.0.4 of 20 December 2006
    Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
168f1dcb
    This file was modified for ClamAV by aCaB <acab@clamav.net>
faaf436a
 
    This program is released under the terms of the license contained
f377e052
    in the file COPYING.bzip2.
faaf436a
    ------------------------------------------------------------------ */
 
 /* CHANGES
    0.9.0    -- original version.
    0.9.0a/b -- no changes in this file.
    0.9.0c   -- made zero-length BZ_FLUSH work correctly in bzCompress().
      fixed bzWrite/bzRead to ignore zero-length requests.
      fixed bzread to correctly handle read requests after EOF.
      wrong parameter order in call to bzDecompressInit in
      bzBuffToBuffDecompress.  Fixed.
 */
 
 #if HAVE_CONFIG_H
 #include "clamav-config.h"
 #endif
 
60d8d2c3
 #include "clamav.h"
faaf436a
 #include "bzlib_private.h"
 #include "others.h"
 
 /*---------------------------------------------------*/
 static
 void makeMaps_d ( DState* s )
 {
    Int32 i;
    s->nInUse = 0;
    for (i = 0; i < 256; i++)
       if (s->inUse[i]) {
          s->seqToUnseq[s->nInUse] = i;
          s->nInUse++;
       }
 }
 
 
 /*---------------------------------------------------*/
 #define RETURN(rrr)                               \
    { retVal = rrr; goto save_state_and_return; };
 
 #define GET_BITS(lll,vvv,nnn)                     \
    case lll: s->state = lll;                      \
    while (True) {                                 \
       if (s->bsLive >= nnn) {                     \
          UInt32 v;                                \
          v = (s->bsBuff >>                        \
              (s->bsLive-nnn)) & ((1 << nnn)-1);   \
          s->bsLive -= nnn;                        \
          vvv = v;                                 \
          break;                                   \
       }                                           \
       if (s->strm->avail_in == 0) RETURN(BZ_OK);  \
       s->bsBuff                                   \
          = (s->bsBuff << 8) |                     \
            ((UInt32)                              \
               (*(s->strm->next_in)));		  \
       s->bsLive += 8;                             \
       s->strm->next_in++;                         \
       s->strm->avail_in--;                        \
       s->strm->total_in_lo32++;                   \
       if (s->strm->total_in_lo32 == 0)            \
          s->strm->total_in_hi32++;                \
    }
 
 #define GET_UCHAR(lll,uuu)                        \
    GET_BITS(lll,uuu,8)
 
 #define GET_BIT(lll,uuu)                          \
    GET_BITS(lll,uuu,1)
 
 /*---------------------------------------------------*/
 #define GET_MTF_VAL(label1,label2,lval)           \
 {                                                 \
    if (groupPos == 0) {                           \
       groupNo++;                                  \
       if (groupNo >= nSelectors)                  \
          RETURN(BZ_DATA_ERROR);                   \
       groupPos = BZ_G_SIZE;                       \
       gSel = s->selector[groupNo];                \
       gMinlen = s->minLens[gSel];                 \
       gLimit = &(s->limit[gSel][0]);              \
       gPerm = &(s->perm[gSel][0]);                \
       gBase = &(s->base[gSel][0]);                \
    }                                              \
    groupPos--;                                    \
    zn = gMinlen;                                  \
    GET_BITS(label1, zvec, zn);                    \
    while (1) {                                    \
       if (zn > 20 /* the longest code */)         \
          RETURN(BZ_DATA_ERROR);                   \
       if (zvec <= gLimit[zn]) break;              \
       zn++;                                       \
       GET_BIT(label2, zj);                        \
       zvec = (zvec << 1) | zj;                    \
    };                                             \
    if (zvec - gBase[zn] < 0                       \
        || zvec - gBase[zn] >= BZ_MAX_ALPHA_SIZE)  \
       RETURN(BZ_DATA_ERROR);                      \
    lval = gPerm[zvec - gBase[zn]];                \
 }
 
ae55464f
 /*---------------------------------------------------*/
 
 inline static Int32 indexIntoF ( Int32 indx, Int32 *cftab )
 {
    Int32 nb, na, mid;
    nb = 0;
    na = 256;
    do {
       mid = (nb + na) >> 1;
       if (indx >= cftab[mid]) nb = mid; else na = mid;
    }
    while (na - nb != 1);
    return nb;
 }
faaf436a
 
 /*---------------------------------------------------*/
 /* Return  True iff data corruption is discovered.
    Returns False if there is no problem.
 */
 static
 Bool unRLE_obuf_to_output_FAST ( DState* s )
 {
    UChar k1;
 
 /*    if (s->blockRandomised) { */
 
 /*       while (True) { */
 /*          /\* try to finish existing run *\/ */
 /*          while (True) { */
 /*             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 ); */
 /*             s->state_out_len--; */
 /*             s->strm->next_out++; */
 /*             s->strm->avail_out--; */
 /*             s->strm->total_out_lo32++; */
 /*             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; */
 /*          } */
 
 /*          /\* can a new run be started? *\/ */
 /*          if (s->nblock_used == s->save_nblock+1) return False; */
0249be88
 
faaf436a
 /*          /\* Only caused by corrupt data stream? *\/ */
 /*          if (s->nblock_used > s->save_nblock+1) */
 /*             return True; */
0249be88
 
faaf436a
 /*          s->state_out_len = 1; */
 /*          s->state_out_ch = s->k0; */
 /*          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;  */
 
 
 
 /*          k1 ^= BZ_RAND_MASK; s->nblock_used++; */
 /*          if (s->nblock_used == s->save_nblock+1) continue; */
 /*          if (k1 != s->k0) { s->k0 = k1; continue; }; */
0249be88
 
faaf436a
 /*          s->state_out_len = 2; */
 /*          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;  */
 /*          k1 ^= BZ_RAND_MASK; s->nblock_used++; */
 /*          if (s->nblock_used == s->save_nblock+1) continue; */
 /*          if (k1 != s->k0) { s->k0 = k1; continue; }; */
0249be88
 
faaf436a
 /*          s->state_out_len = 3; */
 /*          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;  */
 /*          k1 ^= BZ_RAND_MASK; s->nblock_used++; */
 /*          if (s->nblock_used == s->save_nblock+1) continue; */
 /*          if (k1 != s->k0) { s->k0 = k1; continue; }; */
0249be88
 
faaf436a
 /*          BZ_GET_FAST(k1); BZ_RAND_UPD_MASK;  */
 /*          k1 ^= BZ_RAND_MASK; s->nblock_used++; */
 /*          s->state_out_len = ((Int32)k1) + 4; */
 /*          BZ_GET_FAST(s->k0); BZ_RAND_UPD_MASK;  */
 /*          s->k0 ^= BZ_RAND_MASK; s->nblock_used++; */
 /*       } */
 
 /*    } else */ {
 
       /* restore */
       UInt32        c_calculatedBlockCRC = s->calculatedBlockCRC;
       UChar         c_state_out_ch       = s->state_out_ch;
       Int32         c_state_out_len      = s->state_out_len;
       Int32         c_nblock_used        = s->nblock_used;
       Int32         c_k0                 = s->k0;
       UInt32*       c_tt                 = s->tt;
       UInt32        c_tPos               = s->tPos;
       UChar*        cs_next_out          = s->strm->next_out;
       unsigned int  cs_avail_out         = s->strm->avail_out;
2bf90881
       Int32         ro_blockSize100k     = s->blockSize100k;
faaf436a
       /* end restore */
 
       UInt32       avail_out_INIT = cs_avail_out;
       Int32        s_save_nblockPP = s->save_nblock+1;
       unsigned int total_out_lo32_old;
 
       while (True) {
 
          /* try to finish existing run */
          if (c_state_out_len > 0) {
             while (True) {
                if (cs_avail_out == 0) goto return_notr;
                if (c_state_out_len == 1) break;
                *cs_next_out = c_state_out_ch;
 	       /* aCaB BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); */
                c_state_out_len--;
                cs_next_out++;
                cs_avail_out--;
             }
             s_state_out_len_eq_one:
             {
0249be88
                if (cs_avail_out == 0) {
faaf436a
                   c_state_out_len = 1; goto return_notr;
                };
                *cs_next_out = c_state_out_ch;
 	       /* aCaB BZ_UPDATE_CRC ( c_calculatedBlockCRC, c_state_out_ch ); */
                cs_next_out++;
                cs_avail_out--;
             }
0249be88
          }
faaf436a
          /* 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;
0249be88
          };
faaf436a
          c_state_out_ch = c_k0;
          BZ_GET_FAST_C(k1); c_nblock_used++;
0249be88
          if (k1 != c_k0) {
             c_k0 = k1; goto s_state_out_len_eq_one;
faaf436a
          };
0249be88
          if (c_nblock_used == s_save_nblockPP)
faaf436a
             goto s_state_out_len_eq_one;
0249be88
 
faaf436a
          c_state_out_len = 2;
          BZ_GET_FAST_C(k1); c_nblock_used++;
          if (c_nblock_used == s_save_nblockPP) continue;
          if (k1 != c_k0) { c_k0 = k1; continue; };
0249be88
 
faaf436a
          c_state_out_len = 3;
          BZ_GET_FAST_C(k1); c_nblock_used++;
          if (c_nblock_used == s_save_nblockPP) continue;
          if (k1 != c_k0) { c_k0 = k1; continue; };
0249be88
 
faaf436a
          BZ_GET_FAST_C(k1); c_nblock_used++;
          c_state_out_len = ((Int32)k1) + 4;
          BZ_GET_FAST_C(c_k0); c_nblock_used++;
       }
 
       return_notr:
       total_out_lo32_old = s->strm->total_out_lo32;
       s->strm->total_out_lo32 += (avail_out_INIT - cs_avail_out);
       if (s->strm->total_out_lo32 < total_out_lo32_old)
          s->strm->total_out_hi32++;
 
       /* save */
       s->calculatedBlockCRC = c_calculatedBlockCRC;
       s->state_out_ch       = c_state_out_ch;
       s->state_out_len      = c_state_out_len;
       s->nblock_used        = c_nblock_used;
       s->k0                 = c_k0;
       s->tt                 = c_tt;
       s->tPos               = c_tPos;
       s->strm->next_out     = cs_next_out;
       s->strm->avail_out    = cs_avail_out;
       /* end save */
    }
    return False;
 }
 
 
 /*---------------------------------------------------*/
 /* Return  True iff data corruption is discovered.
    Returns False if there is no problem.
 */
 static
 Bool unRLE_obuf_to_output_SMALL ( DState* s )
 {
    UChar k1;
 
 /*    if (s->blockRandomised) { */
 
 /*       while (True) { */
 /*          /\* try to finish existing run *\/ */
 /*          while (True) { */
 /*             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 ); */
 /*             s->state_out_len--; */
 /*             s->strm->next_out++; */
 /*             s->strm->avail_out--; */
 /*             s->strm->total_out_lo32++; */
 /*             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++; */
 /*          } */
0249be88
 
faaf436a
 /*          /\* can a new run be started? *\/ */
 /*          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; */
0249be88
 
faaf436a
 /*          s->state_out_len = 1; */
 /*          s->state_out_ch = s->k0; */
 /*          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;  */
 /*          k1 ^= BZ_RAND_MASK; s->nblock_used++; */
 /*          if (s->nblock_used == s->save_nblock+1) continue; */
 /*          if (k1 != s->k0) { s->k0 = k1; continue; }; */
0249be88
 
faaf436a
 /*          s->state_out_len = 2; */
 /*          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;  */
 /*          k1 ^= BZ_RAND_MASK; s->nblock_used++; */
 /*          if (s->nblock_used == s->save_nblock+1) continue; */
 /*          if (k1 != s->k0) { s->k0 = k1; continue; }; */
0249be88
 
faaf436a
 /*          s->state_out_len = 3; */
 /*          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;  */
 /*          k1 ^= BZ_RAND_MASK; s->nblock_used++; */
 /*          if (s->nblock_used == s->save_nblock+1) continue; */
 /*          if (k1 != s->k0) { s->k0 = k1; continue; }; */
0249be88
 
faaf436a
 /*          BZ_GET_SMALL(k1); BZ_RAND_UPD_MASK;  */
 /*          k1 ^= BZ_RAND_MASK; s->nblock_used++; */
 /*          s->state_out_len = ((Int32)k1) + 4; */
 /*          BZ_GET_SMALL(s->k0); BZ_RAND_UPD_MASK;  */
 /*          s->k0 ^= BZ_RAND_MASK; s->nblock_used++; */
 /*       } */
 
 /*    } else */ {
 
       while (True) {
          /* try to finish existing run */
          while (True) {
             if (s->strm->avail_out == 0) return False;
             if (s->state_out_len == 0) break;
             *(s->strm->next_out) = s->state_out_ch;
 	    /* aCaB BZ_UPDATE_CRC ( s->calculatedBlockCRC, s->state_out_ch ); */
             s->state_out_len--;
             s->strm->next_out++;
             s->strm->avail_out--;
             s->strm->total_out_lo32++;
             if (s->strm->total_out_lo32 == 0) s->strm->total_out_hi32++;
          }
0249be88
 
faaf436a
          /* can a new run be started? */
          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;
0249be88
 
faaf436a
          s->state_out_len = 1;
          s->state_out_ch = s->k0;
          BZ_GET_SMALL(k1); s->nblock_used++;
          if (s->nblock_used == s->save_nblock+1) continue;
          if (k1 != s->k0) { s->k0 = k1; continue; };
0249be88
 
faaf436a
          s->state_out_len = 2;
          BZ_GET_SMALL(k1); s->nblock_used++;
          if (s->nblock_used == s->save_nblock+1) continue;
          if (k1 != s->k0) { s->k0 = k1; continue; };
0249be88
 
faaf436a
          s->state_out_len = 3;
          BZ_GET_SMALL(k1); s->nblock_used++;
          if (s->nblock_used == s->save_nblock+1) continue;
          if (k1 != s->k0) { s->k0 = k1; continue; };
0249be88
 
faaf436a
          BZ_GET_SMALL(k1); s->nblock_used++;
          s->state_out_len = ((Int32)k1) + 4;
          BZ_GET_SMALL(s->k0); s->nblock_used++;
       }
 
    }
 }
ae55464f
 /*---------------------------------------------------*/
 
 static void CreateDecodeTables ( Int32 *limit,
                                 Int32 *base,
                                 Int32 *perm,
                                 UChar *length,
                                 Int32 minLen,
                                 Int32 maxLen,
                                 Int32 alphaSize )
 {
    Int32 pp, i, j, vec;
 
    pp = 0;
    for (i = minLen; i <= maxLen; i++)
       for (j = 0; j < alphaSize; j++)
          if (length[j] == i) { perm[pp] = j; pp++; };
 
    for (i = 0; i < BZ_MAX_CODE_LEN; i++) base[i] = 0;
    for (i = 0; i < alphaSize; i++) base[length[i]+1]++;
 
    for (i = 1; i < BZ_MAX_CODE_LEN; i++) base[i] += base[i-1];
faaf436a
 
ae55464f
    for (i = 0; i < BZ_MAX_CODE_LEN; i++) limit[i] = 0;
    vec = 0;
 
    for (i = minLen; i <= maxLen; i++) {
       vec += (base[i+1] - base[i]);
       limit[i] = vec-1;
       vec <<= 1;
    }
    for (i = minLen + 1; i <= maxLen; i++)
       base[i] = ((limit[i-1] + 1) << 1) - base[i];
 }
faaf436a
 
 /*---------------------------------------------------*/
 static Int32 BZ2_decompress ( DState* s )
 {
    UChar      uc;
    Int32      retVal;
    Int32      minLen, maxLen;
    nsis_bzstream* strm = s->strm;
 
    /* stuff that needs to be saved/restored */
    Int32  i;
    Int32  j;
    Int32  t;
    Int32  alphaSize;
    Int32  nGroups;
    Int32  nSelectors;
    Int32  EOB;
    Int32  groupNo;
    Int32  groupPos;
    Int32  nextSym;
    Int32  nblockMAX;
    Int32  nblock;
    Int32  es;
    Int32  N;
    Int32  curr;
    Int32  zt;
0249be88
    Int32  zn;
faaf436a
    Int32  zvec;
    Int32  zj;
    Int32  gSel;
    Int32  gMinlen;
    Int32* gLimit;
    Int32* gBase;
    Int32* gPerm;
 
    if (s->state == BZ_X_MAGIC_1) {
       /*initialise the save area*/
       s->save_i           = 0;
       s->save_j           = 0;
       s->save_t           = 0;
       s->save_alphaSize   = 0;
       s->save_nGroups     = 0;
       s->save_nSelectors  = 0;
       s->save_EOB         = 0;
       s->save_groupNo     = 0;
       s->save_groupPos    = 0;
       s->save_nextSym     = 0;
       s->save_nblockMAX   = 0;
       s->save_nblock      = 0;
       s->save_es          = 0;
       s->save_N           = 0;
       s->save_curr        = 0;
       s->save_zt          = 0;
       s->save_zn          = 0;
       s->save_zvec        = 0;
       s->save_zj          = 0;
       s->save_gSel        = 0;
       s->save_gMinlen     = 0;
       s->save_gLimit      = NULL;
       s->save_gBase       = NULL;
       s->save_gPerm       = NULL;
    }
 
    /*restore from the save area*/
    i           = s->save_i;
    j           = s->save_j;
    t           = s->save_t;
    alphaSize   = s->save_alphaSize;
    nGroups     = s->save_nGroups;
    nSelectors  = s->save_nSelectors;
    EOB         = s->save_EOB;
    groupNo     = s->save_groupNo;
    groupPos    = s->save_groupPos;
    nextSym     = s->save_nextSym;
    nblockMAX   = s->save_nblockMAX;
    nblock      = s->save_nblock;
    es          = s->save_es;
    N           = s->save_N;
    curr        = s->save_curr;
    zt          = s->save_zt;
0249be88
    zn          = s->save_zn;
faaf436a
    zvec        = s->save_zvec;
    zj          = s->save_zj;
    gSel        = s->save_gSel;
    gMinlen     = s->save_gMinlen;
    gLimit      = s->save_gLimit;
    gBase       = s->save_gBase;
    gPerm       = s->save_gPerm;
 
    retVal = BZ_OK;
 
    switch (s->state) {
 
      /* aCaB
       GET_UCHAR(BZ_X_MAGIC_1, uc);
       if (uc != BZ_HDR_B) RETURN(BZ_DATA_ERROR_MAGIC);
 
       GET_UCHAR(BZ_X_MAGIC_2, uc);
       if (uc != BZ_HDR_Z) RETURN(BZ_DATA_ERROR_MAGIC);
 
       GET_UCHAR(BZ_X_MAGIC_3, uc)
       if (uc != BZ_HDR_h) RETURN(BZ_DATA_ERROR_MAGIC);
 
       GET_BITS(BZ_X_MAGIC_4, s->blockSize100k, 8)
0249be88
       if (s->blockSize100k < (BZ_HDR_0 + 1) ||
faaf436a
           s->blockSize100k > (BZ_HDR_0 + 9)) RETURN(BZ_DATA_ERROR_MAGIC);
       s->blockSize100k -= BZ_HDR_0;
      */
 
    case BZ_X_MAGIC_1:
 
       s->blockSize100k = 9;
 
       if (s->smallDecompress) {
          s->ll16 = BZALLOC( s->blockSize100k * 100000 * sizeof(UInt16) );
0249be88
          s->ll4  = BZALLOC(
                       ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar)
faaf436a
                    );
          if (s->ll16 == NULL || s->ll4 == NULL) RETURN(BZ_MEM_ERROR);
       } else {
          s->tt  = BZALLOC( s->blockSize100k * 100000 * sizeof(Int32) );
          if (s->tt == NULL) RETURN(BZ_MEM_ERROR);
       }
 
       GET_UCHAR(BZ_X_BLKHDR_1, uc);
 
       if (uc == 0x17) goto endhdr_2;
       if (uc != 0x31) RETURN(BZ_DATA_ERROR);
 
       /* aCaB
       GET_UCHAR(BZ_X_BLKHDR_2, uc);
       if (uc != 0x41) RETURN(BZ_DATA_ERROR);
       GET_UCHAR(BZ_X_BLKHDR_3, uc);
       if (uc != 0x59) RETURN(BZ_DATA_ERROR);
       GET_UCHAR(BZ_X_BLKHDR_4, uc);
       if (uc != 0x26) RETURN(BZ_DATA_ERROR);
       GET_UCHAR(BZ_X_BLKHDR_5, uc);
       if (uc != 0x53) RETURN(BZ_DATA_ERROR);
       GET_UCHAR(BZ_X_BLKHDR_6, uc);
       if (uc != 0x59) RETURN(BZ_DATA_ERROR);
 
       s->currBlockNo++;
       if (s->verbosity >= 2)
          VPrintf1 ( "\n    [%d: huff+mtf ", s->currBlockNo );
0249be88
 
faaf436a
       s->storedBlockCRC = 0;
       GET_UCHAR(BZ_X_BCRC_1, uc);
       s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
       GET_UCHAR(BZ_X_BCRC_2, uc);
       s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
       GET_UCHAR(BZ_X_BCRC_3, uc);
       s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
       GET_UCHAR(BZ_X_BCRC_4, uc);
       s->storedBlockCRC = (s->storedBlockCRC << 8) | ((UInt32)uc);
 
 
       GET_BITS(BZ_X_RANDBIT, s->blockRandomised, 1);
       */
 
       s->origPtr = 0;
       GET_UCHAR(BZ_X_ORIGPTR_1, uc);
       s->origPtr = (s->origPtr << 8) | ((Int32)uc);
       GET_UCHAR(BZ_X_ORIGPTR_2, uc);
       s->origPtr = (s->origPtr << 8) | ((Int32)uc);
       GET_UCHAR(BZ_X_ORIGPTR_3, uc);
       s->origPtr = (s->origPtr << 8) | ((Int32)uc);
 
       if (s->origPtr < 0)
          RETURN(BZ_DATA_ERROR);
0249be88
       if (s->origPtr > 10 + 100000*s->blockSize100k)
faaf436a
          RETURN(BZ_DATA_ERROR);
 
       /*--- Receive the mapping table ---*/
       for (i = 0; i < 16; i++) {
          GET_BIT(BZ_X_MAPPING_1, uc);
0249be88
          if (uc == 1)
             s->inUse16[i] = True; else
faaf436a
             s->inUse16[i] = False;
       }
 
       for (i = 0; i < 256; i++) s->inUse[i] = False;
 
       for (i = 0; i < 16; i++)
          if (s->inUse16[i])
             for (j = 0; j < 16; j++) {
                GET_BIT(BZ_X_MAPPING_2, uc);
                if (uc == 1) s->inUse[i * 16 + j] = True;
             }
       makeMaps_d ( s );
       if (s->nInUse == 0) RETURN(BZ_DATA_ERROR);
       alphaSize = s->nInUse+2;
 
       /*--- Now the selectors ---*/
       GET_BITS(BZ_X_SELECTOR_1, nGroups, 3);
       if (nGroups < 2 || nGroups > 6) RETURN(BZ_DATA_ERROR);
       GET_BITS(BZ_X_SELECTOR_2, nSelectors, 15);
0249be88
       if (nSelectors < 1 || nSelectors > BZ_MAX_SELECTORS) RETURN(BZ_DATA_ERROR);
faaf436a
       for (i = 0; i < nSelectors; i++) {
          j = 0;
          while (True) {
             GET_BIT(BZ_X_SELECTOR_3, uc);
             if (uc == 0) break;
             j++;
             if (j >= nGroups) RETURN(BZ_DATA_ERROR);
          }
          s->selectorMtf[i] = j;
       }
 
       /*--- Undo the MTF values for the selectors. ---*/
       {
          UChar pos[BZ_N_GROUPS], tmp, v;
          for (v = 0; v < nGroups; v++) pos[v] = v;
0249be88
 
faaf436a
          for (i = 0; i < nSelectors; i++) {
             v = s->selectorMtf[i];
             tmp = pos[v];
             while (v > 0) { pos[v] = pos[v-1]; v--; }
             pos[0] = tmp;
             s->selector[i] = tmp;
          }
       }
 
       /*--- Now the coding tables ---*/
       for (t = 0; t < nGroups; t++) {
          GET_BITS(BZ_X_CODING_1, curr, 5);
          for (i = 0; i < alphaSize; i++) {
             while (True) {
                if (curr < 1 || curr > 20) RETURN(BZ_DATA_ERROR);
                GET_BIT(BZ_X_CODING_2, uc);
                if (uc == 0) break;
                GET_BIT(BZ_X_CODING_3, uc);
                if (uc == 0) curr++; else curr--;
             }
             s->len[t][i] = curr;
          }
       }
 
       /*--- Create the Huffman decoding tables ---*/
       for (t = 0; t < nGroups; t++) {
          minLen = 32;
          maxLen = 0;
          for (i = 0; i < alphaSize; i++) {
             if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
             if (s->len[t][i] < minLen) minLen = s->len[t][i];
          }
0249be88
          CreateDecodeTables (
             &(s->limit[t][0]),
             &(s->base[t][0]),
             &(s->perm[t][0]),
faaf436a
             &(s->len[t][0]),
             minLen, maxLen, alphaSize
          );
          s->minLens[t] = minLen;
       }
 
       /*--- Now the MTF values ---*/
 
       EOB      = s->nInUse+1;
       nblockMAX = 100000 * s->blockSize100k;
       groupNo  = -1;
       groupPos = 0;
 
       for (i = 0; i <= 255; i++) s->unzftab[i] = 0;
 
       /*-- MTF init --*/
       {
          Int32 ii, jj, kk;
          kk = MTFA_SIZE-1;
          for (ii = 256 / MTFL_SIZE - 1; ii >= 0; ii--) {
             for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
                s->mtfa[kk] = (UChar)(ii * MTFL_SIZE + jj);
                kk--;
             }
             s->mtfbase[ii] = kk + 1;
          }
       }
       /*-- end MTF init --*/
 
       nblock = 0;
       GET_MTF_VAL(BZ_X_MTF_1, BZ_X_MTF_2, nextSym);
 
       while (True) {
 
          if (nextSym == EOB) break;
 
          if (nextSym == BZ_RUNA || nextSym == BZ_RUNB) {
 
             es = -1;
             N = 1;
             do {
fcd80914
                /* 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);
faaf436a
                if (nextSym == BZ_RUNA) es = es + (0+1) * N; else
                if (nextSym == BZ_RUNB) es = es + (1+1) * N;
                N = N * 2;
                GET_MTF_VAL(BZ_X_MTF_3, BZ_X_MTF_4, nextSym);
             }
                while (nextSym == BZ_RUNA || nextSym == BZ_RUNB);
 
             es++;
             uc = s->seqToUnseq[ s->mtfa[s->mtfbase[0]] ];
             s->unzftab[uc] += es;
 
             if (s->smallDecompress)
                while (es > 0) {
                   if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
                   s->ll16[nblock] = (UInt16)uc;
                   nblock++;
                   es--;
                }
             else
                while (es > 0) {
                   if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
                   s->tt[nblock] = (UInt32)uc;
                   nblock++;
                   es--;
                };
 
             continue;
 
          } else {
 
             if (nblock >= nblockMAX) RETURN(BZ_DATA_ERROR);
 
             /*-- uc = MTF ( nextSym-1 ) --*/
             {
                Int32 ii, jj, kk, pp, lno, off;
                UInt32 nn;
                nn = (UInt32)(nextSym - 1);
 
                if (nn < MTFL_SIZE) {
                   /* avoid general-case expense */
                   pp = s->mtfbase[0];
                   uc = s->mtfa[pp+nn];
                   while (nn > 3) {
                      Int32 z = pp+nn;
                      s->mtfa[(z)  ] = s->mtfa[(z)-1];
                      s->mtfa[(z)-1] = s->mtfa[(z)-2];
                      s->mtfa[(z)-2] = s->mtfa[(z)-3];
                      s->mtfa[(z)-3] = s->mtfa[(z)-4];
                      nn -= 4;
                   }
0249be88
                   while (nn > 0) {
                      s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--;
faaf436a
                   };
                   s->mtfa[pp] = uc;
0249be88
                } else {
faaf436a
                   /* general case */
                   lno = nn / MTFL_SIZE;
                   off = nn % MTFL_SIZE;
                   pp = s->mtfbase[lno] + off;
                   uc = s->mtfa[pp];
0249be88
                   while (pp > s->mtfbase[lno]) {
                      s->mtfa[pp] = s->mtfa[pp-1]; pp--;
faaf436a
                   };
                   s->mtfbase[lno]++;
                   while (lno > 0) {
                      s->mtfbase[lno]--;
0249be88
                      s->mtfa[s->mtfbase[lno]]
faaf436a
                         = s->mtfa[s->mtfbase[lno-1] + MTFL_SIZE - 1];
                      lno--;
                   }
                   s->mtfbase[0]--;
                   s->mtfa[s->mtfbase[0]] = uc;
                   if (s->mtfbase[0] == 0) {
                      kk = MTFA_SIZE-1;
                      for (ii = 256 / MTFL_SIZE-1; ii >= 0; ii--) {
                         for (jj = MTFL_SIZE-1; jj >= 0; jj--) {
                            s->mtfa[kk] = s->mtfa[s->mtfbase[ii] + jj];
                            kk--;
                         }
                         s->mtfbase[ii] = kk + 1;
                      }
                   }
                }
             }
             /*-- end uc = MTF ( nextSym-1 ) --*/
 
             s->unzftab[s->seqToUnseq[uc]]++;
             if (s->smallDecompress)
                s->ll16[nblock] = (UInt16)(s->seqToUnseq[uc]); else
                s->tt[nblock]   = (UInt32)(s->seqToUnseq[uc]);
             nblock++;
 
             GET_MTF_VAL(BZ_X_MTF_5, BZ_X_MTF_6, nextSym);
             continue;
          }
       }
 
       /* Now we know what nblock is, we can do a better sanity
          check on s->origPtr.
       */
       if (s->origPtr < 0 || s->origPtr >= nblock)
          RETURN(BZ_DATA_ERROR);
 
       /*-- Set up cftab to facilitate generation of T^(-1) --*/
fcd80914
       /* 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. */
faaf436a
       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];
fcd80914
       /* Check: cftab entries in range. */
faaf436a
       for (i = 0; i <= 256; i++) {
          if (s->cftab[i] < 0 || s->cftab[i] > nblock) {
             RETURN(BZ_DATA_ERROR);
          }
       }
fcd80914
       /* Check: cftab entries non-descending. */
       for (i = 1; i <= 256; i++) {
          if (s->cftab[i-1] > s->cftab[i]) {
             RETURN(BZ_DATA_ERROR);
          }
       }
 
faaf436a
       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" );
 
       if (s->smallDecompress) {
 
          /*-- Make a copy of cftab, used in generation of T --*/
          for (i = 0; i <= 256; i++) s->cftabCopy[i] = s->cftab[i];
 
          /*-- compute the T vector --*/
          for (i = 0; i < nblock; i++) {
             uc = (UChar)(s->ll16[i]);
             SET_LL(i, s->cftabCopy[uc]);
             s->cftabCopy[uc]++;
          }
 
          /*-- Compute T^(-1) by pointer reversal on T --*/
          i = s->origPtr;
          j = GET_LL(i);
          do {
             Int32 tmp = GET_LL(j);
             SET_LL(j, i);
             i = j;
             j = tmp;
          }
             while (i != s->origPtr);
 
          s->tPos = s->origPtr;
          s->nblock_used = 0;
 	 /* aCaB
          if (s->blockRandomised) {
             BZ_RAND_INIT_MASK;
             BZ_GET_SMALL(s->k0); s->nblock_used++;
0249be88
             BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
faaf436a
 	    } else */{
             BZ_GET_SMALL(s->k0); s->nblock_used++;
          }
 
       } else {
 
          /*-- compute the T^(-1) vector --*/
          for (i = 0; i < nblock; i++) {
             uc = (UChar)(s->tt[i] & 0xff);
             s->tt[s->cftab[uc]] |= (i << 8);
             s->cftab[uc]++;
          }
 
          s->tPos = s->tt[s->origPtr] >> 8;
          s->nblock_used = 0;
 	 /* aCaB
          if (s->blockRandomised) {
             BZ_RAND_INIT_MASK;
             BZ_GET_FAST(s->k0); s->nblock_used++;
0249be88
             BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK;
faaf436a
 	    } else */{
             BZ_GET_FAST(s->k0); s->nblock_used++;
          }
 
       }
 
       RETURN(BZ_OK);
 
 
 
     endhdr_2:
       /* aCaB
       GET_UCHAR(BZ_X_ENDHDR_2, uc);
       if (uc != 0x72) RETURN(BZ_DATA_ERROR);
       GET_UCHAR(BZ_X_ENDHDR_3, uc);
       if (uc != 0x45) RETURN(BZ_DATA_ERROR);
       GET_UCHAR(BZ_X_ENDHDR_4, uc);
       if (uc != 0x38) RETURN(BZ_DATA_ERROR);
       GET_UCHAR(BZ_X_ENDHDR_5, uc);
       if (uc != 0x50) RETURN(BZ_DATA_ERROR);
       GET_UCHAR(BZ_X_ENDHDR_6, uc);
       if (uc != 0x90) RETURN(BZ_DATA_ERROR);
 
       s->storedCombinedCRC = 0;
       GET_UCHAR(BZ_X_CCRC_1, uc);
       s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
       GET_UCHAR(BZ_X_CCRC_2, uc);
       s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
       GET_UCHAR(BZ_X_CCRC_3, uc);
       s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
       GET_UCHAR(BZ_X_CCRC_4, uc);
       s->storedCombinedCRC = (s->storedCombinedCRC << 8) | ((UInt32)uc);
       */
       s->state = BZ_X_IDLE;
       RETURN(BZ_STREAM_END);
 
    default: /* aCaB AssertH ( False, 4001 ); */
      RETURN(BZ_DATA_ERROR);
    }
 
    /* aCaB AssertH ( False, 4002 ); */
    RETURN(BZ_DATA_ERROR);
 
    save_state_and_return:
 
    s->save_i           = i;
    s->save_j           = j;
    s->save_t           = t;
    s->save_alphaSize   = alphaSize;
    s->save_nGroups     = nGroups;
    s->save_nSelectors  = nSelectors;
    s->save_EOB         = EOB;
    s->save_groupNo     = groupNo;
    s->save_groupPos    = groupPos;
    s->save_nextSym     = nextSym;
    s->save_nblockMAX   = nblockMAX;
    s->save_nblock      = nblock;
    s->save_es          = es;
    s->save_N           = N;
    s->save_curr        = curr;
    s->save_zt          = zt;
    s->save_zn          = zn;
    s->save_zvec        = zvec;
    s->save_zj          = zj;
    s->save_gSel        = gSel;
    s->save_gMinlen     = gMinlen;
    s->save_gLimit      = gLimit;
    s->save_gBase       = gBase;
    s->save_gPerm       = gPerm;
 
0249be88
    return retVal;
faaf436a
 }
 
 
 /*---------------------------------------------------*/
 static
 int bz_config_ok ( void )
 {
    if (sizeof(int)   != 4) return 0;
    if (sizeof(short) != 2) return 0;
    if (sizeof(char)  != 1) return 0;
    return 1;
 }
 
 
 /*---------------------------------------------------*/
 static
 void* default_bzalloc ( void* opaque, Int32 items, Int32 size )
 {
cd94be7a
     void* v = cli_malloc ( items * size );
ac49130b
     UNUSEDPARAM(opaque);
cd94be7a
     return v;
faaf436a
 }
 
 static
 void default_bzfree ( void* opaque, void* addr )
 {
cd94be7a
     UNUSEDPARAM(opaque);
     if (addr != NULL) free ( addr );
faaf436a
 }
 
 /*---------------------------------------------------*/
0249be88
 int BZ_API(nsis_BZ2_bzDecompressInit)
                      ( nsis_bzstream* strm,
faaf436a
                        int        verbosity,
                        int        small )
 {
    DState* s;
 
    if (!bz_config_ok()) return BZ_CONFIG_ERROR;
 
    if (strm == NULL) return BZ_PARAM_ERROR;
    if (small != 0 && small != 1) return BZ_PARAM_ERROR;
    if (verbosity < 0 || verbosity > 4) return BZ_PARAM_ERROR;
 
    if (strm->bzalloc == NULL) strm->bzalloc = default_bzalloc;
    if (strm->bzfree == NULL) strm->bzfree = default_bzfree;
 
    s = BZALLOC( sizeof(DState) );
    if (s == NULL) return BZ_MEM_ERROR;
    s->strm                  = strm;
    strm->state              = s;
    s->state                 = BZ_X_MAGIC_1;
    s->bsLive                = 0;
    s->bsBuff                = 0;
    s->calculatedCombinedCRC = 0;
    strm->total_in_lo32      = 0;
    strm->total_in_hi32      = 0;
    strm->total_out_lo32     = 0;
    strm->total_out_hi32     = 0;
    s->smallDecompress       = (Bool)small;
    s->ll4                   = NULL;
    s->ll16                  = NULL;
    s->tt                    = NULL;
    s->currBlockNo           = 0;
    s->verbosity             = verbosity;
 
    return BZ_OK;
 }
 
 /*---------------------------------------------------*/
 int BZ_API(nsis_BZ2_bzDecompress) ( nsis_bzstream *strm )
 {
    Bool    corrupt;
    DState* s;
    if (strm == NULL) return BZ_PARAM_ERROR;
    s = strm->state;
    if (s == NULL) return BZ_PARAM_ERROR;
    if (s->strm != strm) return BZ_PARAM_ERROR;
 
    while (True) {
       if (s->state == BZ_X_IDLE) return BZ_SEQUENCE_ERROR;
       if (s->state == BZ_X_OUTPUT) {
          if (s->smallDecompress)
             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%08x, 0x%08x}", s->storedBlockCRC,
                           s->calculatedBlockCRC );
             if (s->verbosity >= 2) VPrintf0 ( "]" );
             if (s->calculatedBlockCRC != s->storedBlockCRC)
                return BZ_DATA_ERROR;
             s->calculatedCombinedCRC
                = (s->calculatedCombinedCRC << 1) |
                     (s->calculatedCombinedCRC >> 31);
             s->calculatedCombinedCRC ^= s->calculatedBlockCRC;
 	   */
             s->state = BZ_X_BLKHDR_1;
          } else {
             return BZ_OK;
          }
       }
       if (s->state >= BZ_X_MAGIC_1) {
          Int32 r = BZ2_decompress ( s );
          if (r == BZ_STREAM_END) {
 	   /* aCaB
             if (s->verbosity >= 3)
0249be88
                VPrintf2 ( "\n    combined CRCs: stored = 0x%08x, computed = 0x%08x",
faaf436a
                           s->storedCombinedCRC, s->calculatedCombinedCRC );
             if (s->calculatedCombinedCRC != s->storedCombinedCRC)
                return BZ_DATA_ERROR;
 	   */
             return r;
          }
          if (s->state != BZ_X_OUTPUT) return r;
       }
    }
 
    /* AssertH ( 0, 6001 ); */
    return BZ_DATA_ERROR;
    /* return 0; */  /*NOTREACHED*/
 }
 
 
 /*---------------------------------------------------*/
 int BZ_API(nsis_BZ2_bzDecompressEnd)  ( nsis_bzstream *strm )
 {
    DState* s;
    if (strm == NULL) return BZ_PARAM_ERROR;
    s = strm->state;
    if (s == NULL) return BZ_PARAM_ERROR;
    if (s->strm != strm) return BZ_PARAM_ERROR;
 
    if (s->tt   != NULL) BZFREE(s->tt);
    if (s->ll16 != NULL) BZFREE(s->ll16);
    if (s->ll4  != NULL) BZFREE(s->ll4);
 
    BZFREE(strm->state);
    strm->state = NULL;
 
    return BZ_OK;
 }
 
 /*-------------------------------------------------------------*/
 /*--- end                                           bzlib.c ---*/
 /*-------------------------------------------------------------*/