📄 pgpzinflate.c
字号:
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 + -