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"
 
9f0d9b98
 static const Int32 BZ2_rNums[512] = { 
faaf436a
    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;
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:
             {
                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 {
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;
                   }
                   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) --*/
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++;
             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 ---*/
 /*-------------------------------------------------------------*/