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
 
 #include "bzlib_private.h"
 #include "others.h"
 
 const Int32 BZ2_rNums[512] = { 
    619, 720, 127, 481, 931, 816, 813, 233, 566, 247, 
    985, 724, 205, 454, 863, 491, 741, 242, 949, 214, 
    733, 859, 335, 708, 621, 574, 73, 654, 730, 472, 
    419, 436, 278, 496, 867, 210, 399, 680, 480, 51, 
    878, 465, 811, 169, 869, 675, 611, 697, 867, 561, 
    862, 687, 507, 283, 482, 129, 807, 591, 733, 623, 
    150, 238, 59, 379, 684, 877, 625, 169, 643, 105, 
    170, 607, 520, 932, 727, 476, 693, 425, 174, 647, 
    73, 122, 335, 530, 442, 853, 695, 249, 445, 515, 
    909, 545, 703, 919, 874, 474, 882, 500, 594, 612, 
    641, 801, 220, 162, 819, 984, 589, 513, 495, 799, 
    161, 604, 958, 533, 221, 400, 386, 867, 600, 782, 
    382, 596, 414, 171, 516, 375, 682, 485, 911, 276, 
    98, 553, 163, 354, 666, 933, 424, 341, 533, 870, 
    227, 730, 475, 186, 263, 647, 537, 686, 600, 224, 
    469, 68, 770, 919, 190, 373, 294, 822, 808, 206, 
    184, 943, 795, 384, 383, 461, 404, 758, 839, 887, 
    715, 67, 618, 276, 204, 918, 873, 777, 604, 560, 
    951, 160, 578, 722, 79, 804, 96, 409, 713, 940, 
    652, 934, 970, 447, 318, 353, 859, 672, 112, 785, 
    645, 863, 803, 350, 139, 93, 354, 99, 820, 908, 
    609, 772, 154, 274, 580, 184, 79, 626, 630, 742, 
    653, 282, 762, 623, 680, 81, 927, 626, 789, 125, 
    411, 521, 938, 300, 821, 78, 343, 175, 128, 250, 
    170, 774, 972, 275, 999, 639, 495, 78, 352, 126, 
    857, 956, 358, 619, 580, 124, 737, 594, 701, 612, 
    669, 112, 134, 694, 363, 992, 809, 743, 168, 974, 
    944, 375, 748, 52, 600, 747, 642, 182, 862, 81, 
    344, 805, 988, 739, 511, 655, 814, 334, 249, 515, 
    897, 955, 664, 981, 649, 113, 974, 459, 893, 228, 
    433, 837, 553, 268, 926, 240, 102, 654, 459, 51, 
    686, 754, 806, 760, 493, 403, 415, 394, 687, 700, 
    946, 670, 656, 610, 738, 392, 760, 799, 887, 653, 
    978, 321, 576, 617, 626, 502, 894, 679, 243, 440, 
    680, 879, 194, 572, 640, 724, 926, 56, 204, 700, 
    707, 151, 457, 449, 797, 195, 791, 558, 945, 679, 
    297, 59, 87, 824, 713, 663, 412, 693, 342, 606, 
    134, 108, 571, 364, 631, 212, 174, 643, 304, 329, 
    343, 97, 430, 751, 497, 314, 983, 374, 822, 928, 
    140, 206, 73, 263, 980, 736, 876, 478, 430, 305, 
    170, 514, 364, 692, 829, 82, 855, 953, 676, 246, 
    369, 970, 294, 750, 807, 827, 150, 790, 288, 923, 
    804, 378, 215, 828, 592, 281, 565, 555, 710, 82, 
    896, 831, 547, 261, 524, 462, 293, 465, 502, 56, 
    661, 821, 976, 991, 658, 869, 905, 758, 745, 193, 
    768, 550, 608, 933, 378, 286, 215, 979, 792, 961, 
    61, 688, 793, 644, 986, 403, 106, 366, 905, 644, 
    372, 567, 466, 434, 645, 210, 389, 550, 919, 135, 
    780, 773, 635, 389, 707, 100, 626, 958, 165, 504, 
    920, 176, 193, 713, 857, 265, 203, 50, 668, 108, 
    645, 990, 626, 197, 510, 357, 358, 850, 858, 364, 
    936, 638
 };
 
 /*---------------------------------------------------*/
 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; */
                
 /*          /\* 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; */
 /*          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; }; */
    
 /*          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; }; */
    
 /*          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; }; */
    
 /*          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;
       /* 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:
             {
                if (cs_avail_out == 0) { 
                   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--;
             }
          }   
          /* 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;
          };   
          c_state_out_ch = c_k0;
          BZ_GET_FAST_C(k1); c_nblock_used++;
          if (k1 != c_k0) { 
             c_k0 = k1; goto s_state_out_len_eq_one; 
          };
          if (c_nblock_used == s_save_nblockPP) 
             goto s_state_out_len_eq_one;
    
          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; };
    
          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; };
    
          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++; */
 /*          } */
    
 /*          /\* 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; */
    
 /*          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; }; */
    
 /*          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; }; */
    
 /*          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; }; */
    
 /*          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++;
          }
    
          /* 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;
    
          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; };
    
          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; };
    
          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; };
    
          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;
    Int32  zn; 
    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;
    zn          = s->save_zn; 
    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)
       if (s->blockSize100k < (BZ_HDR_0 + 1) || 
           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) );
          s->ll4  = BZALLOC( 
                       ((1 + s->blockSize100k * 100000) >> 1) * sizeof(UChar) 
                    );
          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 );
  
       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);
       if (s->origPtr > 10 + 100000*s->blockSize100k) 
          RETURN(BZ_DATA_ERROR);
 
       /*--- Receive the mapping table ---*/
       for (i = 0; i < 16; i++) {
          GET_BIT(BZ_X_MAPPING_1, uc);
          if (uc == 1) 
             s->inUse16[i] = True; else 
             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);
       if (nSelectors < 1) RETURN(BZ_DATA_ERROR);
       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;
    
          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];
          }
ae55464f
          CreateDecodeTables ( 
faaf436a
             &(s->limit[t][0]), 
             &(s->base[t][0]), 
             &(s->perm[t][0]), 
             &(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 {
                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;
                   }
                   while (nn > 0) { 
                      s->mtfa[(pp+nn)] = s->mtfa[(pp+nn)-1]; nn--; 
                   };
                   s->mtfa[pp] = uc;
                } else { 
                   /* general case */
                   lno = nn / MTFL_SIZE;
                   off = nn % MTFL_SIZE;
                   pp = s->mtfbase[lno] + off;
                   uc = s->mtfa[pp];
                   while (pp > s->mtfbase[lno]) { 
                      s->mtfa[pp] = s->mtfa[pp-1]; pp--; 
                   };
                   s->mtfbase[lno]++;
                   while (lno > 0) {
                      s->mtfbase[lno]--;
                      s->mtfa[s->mtfbase[lno]] 
                         = 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) --*/
       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) {
             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" );
 
       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++;
             BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
 	    } 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++;
             BZ_RAND_UPD_MASK; s->k0 ^= BZ_RAND_MASK; 
 	    } 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;
 
    return retVal;   
 }
 
 
 /*---------------------------------------------------*/
 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 )
 {
    void* v = cli_malloc ( items * size );
    return v;
 }
 
 static
 void default_bzfree ( void* opaque, void* addr )
 {
    if (addr != NULL) free ( addr );
 }
 
 /*---------------------------------------------------*/
 int BZ_API(nsis_BZ2_bzDecompressInit) 
                      ( nsis_bzstream* strm, 
                        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)
                VPrintf2 ( "\n    combined CRCs: stored = 0x%08x, computed = 0x%08x", 
                           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 ---*/
 /*-------------------------------------------------------------*/