Home | History | Annotate | Download | only in gzip
      1 /* inflate.c -- zlib interface to inflate modules
      2  * Copyright (C) 1995-2002 Mark Adler
      3  * For conditions of distribution and use, see copyright notice in zlib.h
      4  */
      5 
      6 #include "zutil.h"
      7 #include "infblock.h"
      8 
      9 #define  DONE  INFLATE_DONE
     10 #define  BAD   INFLATE_BAD
     11 
     12 typedef enum {
     13       METHOD,   /* waiting for method byte */
     14       FLAG,     /* waiting for flag byte */
     15       DICT4,    /* four dictionary check bytes to go */
     16       DICT3,    /* three dictionary check bytes to go */
     17       DICT2,    /* two dictionary check bytes to go */
     18       DICT1,    /* one dictionary check byte to go */
     19       DICT0,    /* waiting for inflateSetDictionary */
     20       BLOCKS,   /* decompressing blocks */
     21       CHECK4,   /* four check bytes to go */
     22       CHECK3,   /* three check bytes to go */
     23       CHECK2,   /* two check bytes to go */
     24       CHECK1,   /* one check byte to go */
     25       DONE,     /* finished check, done */
     26       BAD}      /* got an error--stay here */
     27 inflate_mode;
     28 
     29 /* inflate private state */
     30 struct internal_state {
     31 
     32   /* mode */
     33   inflate_mode  mode;   /* current inflate mode */
     34 
     35   /* mode dependent information */
     36   union {
     37     uInt method;        /* if FLAGS, method byte */
     38     struct {
     39       uLong was;                /* computed check value */
     40       uLong need;               /* stream check value */
     41     } check;            /* if CHECK, check values to compare */
     42     uInt marker;        /* if BAD, inflateSync's marker bytes count */
     43   } sub;        /* submode */
     44 
     45   /* mode independent information */
     46   int  nowrap;          /* flag for no wrapper */
     47   uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
     48   inflate_blocks_statef
     49     *blocks;            /* current inflate_blocks state */
     50 
     51 };
     52 
     53 
     54 ZEXPORT(int) inflateReset( /* z) */
     55 z_streamp z )
     56 {
     57   if (z == Z_NULL || z->state == Z_NULL)
     58     return Z_STREAM_ERROR;
     59   z->total_in = z->total_out = 0;
     60   z->msg = Z_NULL;
     61   z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
     62   inflate_blocks_reset(z->state->blocks, z, Z_NULL);
     63   Tracev((stderr, "inflate: reset\n"));
     64   return Z_OK;
     65 }
     66 
     67 
     68 ZEXPORT(int) inflateEnd( /* z) */
     69 z_streamp z )
     70 {
     71   if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
     72     return Z_STREAM_ERROR;
     73   if (z->state->blocks != Z_NULL)
     74     inflate_blocks_free(z->state->blocks, z);
     75   ZFREE(z, z->state);
     76   z->state = Z_NULL;
     77   Tracev((stderr, "inflate: end\n"));
     78   return Z_OK;
     79 }
     80 
     81 
     82 ZEXPORT(int) inflateInit2_( /* z, w, version, stream_size) */
     83 z_streamp z,
     84 int w,
     85 const char *version,
     86 int stream_size )
     87 {
     88   if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
     89       stream_size != sizeof(z_stream))
     90       return Z_VERSION_ERROR;
     91 
     92   /* initialize state */
     93   if (z == Z_NULL)
     94     return Z_STREAM_ERROR;
     95   z->msg = Z_NULL;
     96   if (z->zalloc == Z_NULL)
     97   {
     98     z->zalloc = zcalloc;
     99     z->opaque = (voidpf)0;
    100   }
    101   if (z->zfree == Z_NULL) z->zfree = zcfree;
    102   if ((z->state = (struct internal_state FAR *)
    103        ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
    104     return Z_MEM_ERROR;
    105   z->state->blocks = Z_NULL;
    106 
    107   /* handle undocumented nowrap option (no zlib header or check) */
    108   z->state->nowrap = 0;
    109   if (w < 0)
    110   {
    111     w = - w;
    112     z->state->nowrap = 1;
    113   }
    114 
    115   /* set window size */
    116   if (w < 8 || w > 15)
    117   {
    118     inflateEnd(z);
    119     return Z_STREAM_ERROR;
    120   }
    121   z->state->wbits = (uInt)w;
    122 
    123   /* create inflate_blocks state */
    124   if ((z->state->blocks =
    125       inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
    126       == Z_NULL)
    127   {
    128     inflateEnd(z);
    129     return Z_MEM_ERROR;
    130   }
    131   Tracev((stderr, "inflate: allocated\n"));
    132 
    133   /* reset state */
    134   inflateReset(z);
    135   return Z_OK;
    136 }
    137 
    138 
    139 
    140 #undef  NEEDBYTE
    141 #define NEEDBYTE {if(z->avail_in==0)return r;r=f;}
    142 
    143 #undef  NEXTBYTE
    144 #define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
    145 
    146 
    147 ZEXPORT(int) inflate( /* z, f) */
    148 z_streamp z,
    149 int f )
    150 {
    151   int r;
    152   uInt b;
    153 
    154   if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
    155     return Z_STREAM_ERROR;
    156   f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
    157   r = Z_BUF_ERROR;
    158   while (1) switch (z->state->mode)
    159   {
    160     case METHOD:
    161       NEEDBYTE
    162       if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED)
    163       {
    164         z->state->mode = BAD;
    165         z->msg = (char*)"unknown compression method";
    166         z->state->sub.marker = 5;       /* can't try inflateSync */
    167         break;
    168       }
    169       if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
    170       {
    171         z->state->mode = BAD;
    172         z->msg = (char*)"invalid window size";
    173         z->state->sub.marker = 5;       /* can't try inflateSync */
    174         break;
    175       }
    176       z->state->mode = FLAG;
    177     case FLAG:
    178       NEEDBYTE
    179       b = NEXTBYTE;
    180       if (((z->state->sub.method << 8) + b) % 31)
    181       {
    182         z->state->mode = BAD;
    183         z->msg = (char*)"incorrect header check";
    184         z->state->sub.marker = 5;       /* can't try inflateSync */
    185         break;
    186       }
    187       Tracev((stderr, "inflate: zlib header ok\n"));
    188       if (!(b & PRESET_DICT))
    189       {
    190         z->state->mode = BLOCKS;
    191         break;
    192       }
    193       z->state->mode = DICT4;
    194     case DICT4:
    195       NEEDBYTE
    196       z->state->sub.check.need = (uLong)NEXTBYTE << 24;
    197       z->state->mode = DICT3;
    198     case DICT3:
    199       NEEDBYTE
    200       z->state->sub.check.need += (uLong)NEXTBYTE << 16;
    201       z->state->mode = DICT2;
    202     case DICT2:
    203       NEEDBYTE
    204       z->state->sub.check.need += (uLong)NEXTBYTE << 8;
    205       z->state->mode = DICT1;
    206     case DICT1:
    207       NEEDBYTE
    208       z->state->sub.check.need += (uLong)NEXTBYTE;
    209       z->adler = z->state->sub.check.need;
    210       z->state->mode = DICT0;
    211       return Z_NEED_DICT;
    212     case DICT0:
    213       z->state->mode = BAD;
    214       z->msg = (char*)"need dictionary";
    215       z->state->sub.marker = 0;       /* can try inflateSync */
    216       return Z_STREAM_ERROR;
    217     case BLOCKS:
    218       r = inflate_blocks(z->state->blocks, z, r);
    219       if (r == Z_DATA_ERROR)
    220       {
    221         z->state->mode = BAD;
    222         z->state->sub.marker = 0;       /* can try inflateSync */
    223         break;
    224       }
    225       if (r == Z_OK)
    226         r = f;
    227       if (r != Z_STREAM_END)
    228         return r;
    229       r = f;
    230       inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
    231       if (z->state->nowrap)
    232       {
    233         z->state->mode = DONE;
    234         break;
    235       }
    236       z->state->mode = CHECK4;
    237     case CHECK4:
    238       NEEDBYTE
    239       z->state->sub.check.need = (uLong)NEXTBYTE << 24;
    240       z->state->mode = CHECK3;
    241     case CHECK3:
    242       NEEDBYTE
    243       z->state->sub.check.need += (uLong)NEXTBYTE << 16;
    244       z->state->mode = CHECK2;
    245     case CHECK2:
    246       NEEDBYTE
    247       z->state->sub.check.need += (uLong)NEXTBYTE << 8;
    248       z->state->mode = CHECK1;
    249     case CHECK1:
    250       NEEDBYTE
    251       z->state->sub.check.need += (uLong)NEXTBYTE;
    252 
    253       if (z->state->sub.check.was != z->state->sub.check.need)
    254       {
    255         z->state->mode = BAD;
    256         z->msg = (char*)"incorrect data check";
    257         z->state->sub.marker = 5;       /* can't try inflateSync */
    258         break;
    259       }
    260       Tracev((stderr, "inflate: zlib check ok\n"));
    261       z->state->mode = DONE;
    262     case DONE:
    263       return Z_STREAM_END;
    264     case BAD:
    265       return Z_DATA_ERROR;
    266     default:
    267       return Z_STREAM_ERROR;
    268   }
    269 #ifdef NEED_DUMMY_RETURN
    270   return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
    271 #endif
    272 }
    273 
    274