⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pgpzinflate.c

📁 PGP—Pretty Good Privacy
💻 C
📖 第 1 页 / 共 4 页
字号:
        return 1;
      }
      /* Actually, s is set (see GETBITSOR comment) to -1, so reset it */
      s = 0;
      if ((e = t->exop) < 0) {
	do {
	  if (e == -128)
	    return INFERR_BADINPUT;
	  DUMPBITS(t->bits);
	  e = -e;
          t = t->next;
  case 1:
          NEEDBITS2(e, t[(unsigned)b & mask[e]].bits,
                    ctx->t=t; ctx->outptr=w; ctx->numbits=e; ctx->substate=1)
	  t += (unsigned)b & mask[e];
	} while ((e = t->exop) < 0);
      }
      DUMPBITS(t->bits);
      if (e & 16) {         /* then it's a literal */
	*w++ = (unsigned char)t->base;
	if (--r == 0) {
          /* We just filled the output buffer - return */
          SAVEBITBUF;
          ctx->outptr = w;
          ctx->substate = 0;	/* Restart at top of loop */
          return 2;	/* Output buffer full */
	}
	continue;
      }

      if (e & 32)	/* EOB */
	break;	/* Leave infinite loop */

      /*FALLTHROUGH*/
  case 2:
      NEEDBITS(e, ctx->t = t; ctx->outptr=w; ctx->numbits=e; ctx->substate=2)

gotlength:

      /* All data is available - compute total length of block to copy */
      n = t->base + ((unsigned)b & mask[e]);
      DUMPBITS((unsigned)e);

      /*FALLTHROUGH*/
  case 3:
      /* Get distance code - 15 is maximum code size */
      GETBITSOR(15, goto getdistance2)
      t = td + ((unsigned)b & md);
      /* Negative t->exop means there's a subtable of 2^-e entries */
      if ((e = t->exop) < 0) {
	do {
	  if (e == -128)
	    return INFERR_BADINPUT;	/* Invalid code (static table case) */
	  DUMPBITS(t->bits);
	  e = -e;
	  t = t->next + ((unsigned)b & mask[e]);
	} while ((e = t->exop) < 0);
      }
      goto gotdistance;

getdistance2:
      /* We don't even have 15 bits available - do it bit-by-bit. */
      t = td + ((unsigned)b & md);
      /*
       * See if higher-order bits we're missing actually matter.
       * We don't have to try to fill the bit buffer, because we only get
       * here if s (number of following input bytes) is supposed to be zero.
       */
      if (k < (unsigned)t->bits) {
        ctx->outptr = w;
        ctx->copylen = n;
        ctx->substate = 3;
        SAVEBITBUFEMPTY;
        return 1;
      }
      /* Actually (see GETBITSOR comment) s is set to -1, so reset it */
      s = 0;
      /* Negative t->exop means there's a subtable of 2^-e entries */
      if ((e = t->exop) < 0) {
	do {
	  if (e == -128)
	    return INFERR_BADINPUT;	/* Invalid code (static table case) */
	  DUMPBITS(t->bits);
	  e = -e;
	  t = t->next;
  case 4:
          NEEDBITS2(e, t[(unsigned)b & mask[e]].bits, ctx->t=t; ctx->outptr=w;
                       ctx->copylen = n; ctx->numbits=e; ctx->substate=4)
	  t += (unsigned)b & mask[e];
	} while ((e = t->exop) < 0);
      }

gotdistance:
      /* All data is available - compute the base distance */
      DUMPBITS(t->bits);
      d = t->base;
      /*FALLTHROUGH*/
  case 5:
      /* e is number of bits extra following distance code (0..13) */
      NEEDBITS(e, ctx->outptr=w; ctx->copylen=n; ctx->distbase=d;
                  ctx->numbits=e; ctx->substate=5)
      d += ((unsigned)b & mask[e]);
      DUMPBITS((unsigned)e);

#if WSIZE < 32768
      if (d > ctx->slidelen)
	return INFERR_BADINPUT;
#endif

      /* do the copy, with handling for wrapping around end of buffer */
      if ((unsigned)(w - ctx->slide) >= d && w + n < ctx->slideend - 2) {
        /* Simple case - neither source nor dest cross end of buffer */
	p = w - d;
	r -= n + 2;
	*w++ = *p++;
	*w++ = *p++;
	do {
	  *w++ = *p++;
	} while (--n);
      } else {
	n += 2;	/* # of bytes to copy */
	p = ctx->slide + ((w - ctx->slide - d) & ctx->slidemask);  /* src */
	do {
          /* Set e to number of bytes we can copy at once */
	  n -= (e = (unsigned)(e = ctx->slideend - (p>w?p:w)) > n ? n : e);
	  r -= e;
	  do {
	    *w++ = *p++;
	  } while (--e);
	  if (r == 0) {	/* Did we just write everything we could? */
            SAVEBITBUF;
            ctx->outptr = w;
            ctx->copylen = n;
            ctx->distbase = d;	/* Save copy distance to recompute p */
            ctx->substate = 6;
            return 2;	/* Need more output space */
  case 6:
	    p = ctx->slide + ((w - ctx->slide - d) & ctx->slidemask);
	  }
	  if (p == ctx->slideend)
	    p = ctx->slide;
	} while (n);
      }
    } /* for(;;) */
  } /* switch(ctx->subcase) */

EOB:
  /* End of Block */
  ctx->outptr = w;
  SAVEBITBUF;
  ctx->state = STATE_START;
  ctx->substate = 0;

  if (tl && tl != ctx->fixed_tl)
    huft_free(ctx->context, tl);
  if (td && td != ctx->fixed_td)
    huft_free( ctx->context, td);
  ctx->tree1 = 0;
  ctx->tree2 = 0;

  return 0;
}


/*
 * Start state - read 3 bits, which are last block flag (set to 1 on
 * last block), and 2 bits of block type.
 */
static int
infStart(InflateContext *ctx)
{
	ulg b;
	unsigned k;
	int s;
	unsigned char const *g;
	int retval = 0;

	if (ctx->lastblock) {
		ctx->state = STATE_DONE;
		return 0;
	}

	LOADBITBUF;
	NEEDBITS(3, (void)0);

	ctx->lastblock = (int)(b & 1);
	DUMPBITS(1);

	switch(b & 3) {
	case 0:	/* Stored */
		ctx->state = STATE_STOREDLEN;
		break;
	case 1: /* Static - build fixed trees and start decoding */
		retval = infFixedTree( ctx );
		ctx->tree1 = ctx->fixed_tl;
		ctx->bits1 = ctx->fixed_bl;
		ctx->tree2 = ctx->fixed_td;
		ctx->bits2 = ctx->fixed_bd;
		ctx->state = STATE_INFLATE;
		break;
	case 2: /* Dynamic */
		ctx->state = STATE_DYN_HDR;
		break;
	case 3: /* Illegal */
		retval = INFERR_BADINPUT;
		break;
	}

	DUMPBITS(2);
	SAVEBITBUF;

	ctx->substate = 0;
	return retval;
}

/*
 * Get a pointer to available data in the output buffer
 */
unsigned char const *
infGetBytes(InflateContext *ctx, unsigned *len)
{
	*len = ctx->outptr - ctx->readptr;
	return *len ? ctx->readptr : 0;
}

/*
 * Mark data in the output buffer as already read.  We don't start
 * accepting new data until the entire output buffer has been read,
 * at which point the outptr is set back to the beginning of the
 * buffer.
 */
void
infSkipBytes(InflateContext *ctx, unsigned len)
{
	pgpAssert(len <= (unsigned)(ctx->outptr - ctx->readptr));

	ctx->readptr += len;

	/* If at end of buffer, recirculate */
	if (ctx->readptr == ctx->slideend) {
		PGPError dummy;

		pgpAssert(ctx->outptr == ctx->slideend);
		ctx->readptr = ctx->outptr = ctx->slide;
		/* Flush any pending output */
		(void)infWrite(ctx, NULL, 0, &dummy);
	}
}


/*
 * Returns number of bytes written.
 * *error < 0 on error, == 0 if no error (done with input or output full)
 */
size_t
infWrite(InflateContext *ctx, unsigned char const *buf, size_t len,
         PGPError *error)
{
	int i	= 0;

	if (ctx->outptr == ctx->slideend) {
		*error = (ctx->state == STATE_STOP) ?
			kPGPError_NoErr : (PGPError)ctx->substate;
		return 0;	/* Out of output space! */
	}

	ctx->inptr = buf;
	/* Decompression code can't handle more than INT_MAX bytes at a time */
	ctx->inlen = len > INT_MAX ? INT_MAX : (int)len;

	do {
		switch(ctx->state) {
		  case STATE_START:
			i = infStart(ctx);
			break;
		  case STATE_STOREDLEN:
			i = infStoredLen(ctx);
			break;
		  case STATE_STORED:
			i = infStored(ctx);
			break;
		  case STATE_DYN_HDR:
			i = infDynHdr(ctx);
			break;
		  case STATE_DYN_BITS:
			i = infDynBits(ctx);
			break;
		  case STATE_DYN_TREE:
			i = infDynTree(ctx);
			break;
		  case STATE_INFLATE:
			i = infInflate(ctx);
			break;
		  case STATE_DONE:
			if (ctx->inlen || ctx->bufbits > 7)
				i = INFERR_LONG;
#if STRICT
			else if (ctx->bitbuffer & mask[ctx->bufbits])
				i = INFERR_BADINPUT;	/* Unused bits != 0 */
#endif
			else
				i = 2;	/* Read output, please */
			break;
		  case STATE_STOP:
			i = ctx->substate;
			break;
		  default:
		  	i	= 0;
		  	pgpDebugMsg( "impossible state" );
		  	break;
		}
	} while (i == 0);

	if (i < 0) {
		ctx->state = STATE_STOP;
		ctx->substate = i;
		*error = (PGPError)i;
	} else {
		*error = kPGPError_NoErr;
	}

	pgpAssert((size_t)(ctx->inptr - buf) == len - ctx->inlen);
	return (size_t)(ctx->inptr - buf);	/* Bytes read */
}

/*
 * Signal EOF, detecting truncated messages.
 * If another error has been reported, this just repeats it.
 */
/* New version, hopefully useful. */
int
infEOF(InflateContext *ctx)
{
	/* If processing is halted, just return the last error (if any) */
	if (ctx->state == STATE_STOP)
		return ctx->substate;

	/* If expecting still more input, we're short */
	if (ctx->state != STATE_DONE)
		return INFERR_SHORT;

	/* Otherwise, all is well. */
		return 0;
}

InflateContext *
infAlloc( PGPContextRef	context )
{
	InflateContext *ctx;
	unsigned char *slide;

	slide = (unsigned char *)pgpContextMemAlloc( context,
			WSIZE, kPGPMemoryMgrFlags_Clear);
	if (!slide)
		return 0;
	ctx = (InflateContext *)pgpContextMemAlloc( context,
			sizeof(*ctx), kPGPMemoryMgrFlags_Clear);
	if (!ctx) {
		pgpContextMemFree( context, slide);
		return 0;
	}
	ctx->context	= context;
	ctx->slide = slide;
	ctx->slideend = slide+WSIZE;
	ctx->slidelen = WSIZE;
	ctx->slidemask = WSIZE-1;

	ctx->outptr = slide;
	ctx->readptr = slide;

	ctx->state = STATE_START;
	ctx->substate = 0;
	ctx->inlen = 0;
	ctx->bitbuffer = 0;
	ctx->bufbits = 0;
	ctx->lastblock = 0;

	ctx->tree1 = 0;
	ctx->tree2 = 0;

	return ctx;
}

void
infFree(InflateContext *ctx)
{
	PGPContextRef context = ctx->context;

	if (ctx->tree1 && ctx->tree1 != ctx->fixed_tl)
		huft_free(context, ctx->tree1);
	if (ctx->tree2 && ctx->tree2 != ctx->fixed_td)
		huft_free(context, ctx->tree2);
	
	if ( IsntNull( ctx->fixed_tl ) )
	{
		huft_free(context, ctx->fixed_tl);
		ctx->fixed_tl	= NULL;
	}
	if ( IsntNull( ctx->fixed_td ) )
	{
		huft_free(context, ctx->fixed_td);
		ctx->fixed_tl	= NULL;
	}

	if (ctx->slide) {
#if SECURE
		pgpClearMemory(ctx->slide, ctx->slidelen);
#endif
		pgpContextMemFree( context, ctx->slide);
	}
#if SECURE
	pgpClearMemory( ctx,  sizeof(*ctx));
#endif
	pgpContextMemFree( context, ctx);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -