Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 78 additions & 50 deletions source/lv1/puff/puff.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/*
* puff.c
* Copyright (C) 2002-2010 Mark Adler
* Copyright (C) 2002-2013 Mark Adler
* For conditions of distribution and use, see copyright notice in puff.h
* version 2.1, 4 Apr 2010
* version 2.3, 21 Jan 2013
*
* puff.c is a simple inflate written to be an unambiguous way to specify the
* deflate format. It is not written for speed but rather simplicity. As a
Expand All @@ -17,7 +17,7 @@
* All dynamically allocated memory comes from the stack. The stack required
* is less than 2K bytes. This code is compatible with 16-bit int's and
* assumes that long's are at least 32 bits. puff.c uses the short data type,
* assumed to be 16 bits, for arrays in order to to conserve memory. The code
* assumed to be 16 bits, for arrays in order to conserve memory. The code
* works whether integers are stored big endian or little endian.
*
* In the comments below are "Format notes" that describe the inflate process
Expand All @@ -43,15 +43,15 @@
* - Use pointers instead of long to specify source and
* destination sizes to avoid arbitrary 4 GB limits
* 1.2 17 Mar 2002 - Add faster version of decode(), doubles speed (!),
* but leave simple version for readabilty
* but leave simple version for readability
* - Make sure invalid distances detected if pointers
* are 16 bits
* - Fix fixed codes table error
* - Provide a scanning mode for determining size of
* uncompressed data
* 1.3 20 Mar 2002 - Go back to lengths for puff() parameters [Jean-loup]
* 1.3 20 Mar 2002 - Go back to lengths for puff() parameters [Gailly]
* - Add a puff.h file for the interface
* - Add braces in puff() for else do [Jean-loup]
* - Add braces in puff() for else do [Gailly]
* - Use indexes instead of pointers for readability
* 1.4 31 Mar 2002 - Simplify construct() code set check
* - Fix some comments
Expand All @@ -69,13 +69,20 @@
* - Allow TEST code to read from piped stdin
* 2.1 4 Apr 2010 - Avoid variable initialization for happier compilers
* - Avoid unsigned comparisons for even happier compilers
* 2.2 25 Apr 2010 - Fix bug in variable initializations [Oberhumer]
* - Add const where appropriate [Oberhumer]
* - Split if's and ?'s for coverage testing
* - Break out test code to separate file
* - Move NIL to puff.h
* - Allow incomplete code only if single code length is 1
* - Add full code coverage test to Makefile
* 2.3 21 Jan 2013 - Check for invalid code length codes in dynamic blocks
*/

#include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */
#include "puff.h" /* prototype for puff() */

#define local static /* for local function definitions */
#define NIL ((unsigned char *)0) /* for no output option */

/*
* Maximums for allocations and loops. It is not useful to change these --
Expand All @@ -95,7 +102,7 @@ struct state {
unsigned long outcnt; /* bytes written to out so far */

/* input state */
unsigned char *in; /* input buffer */
const unsigned char *in; /* input buffer */
unsigned long inlen; /* available input at in */
unsigned long incnt; /* bytes read so far */
int bitbuf; /* bit buffer */
Expand Down Expand Up @@ -123,7 +130,8 @@ local int bits(struct state *s, int need)
/* load at least need bits into val */
val = s->bitbuf;
while (s->bitcnt < need) {
if (s->incnt == s->inlen) longjmp(s->env, 1); /* out of input */
if (s->incnt == s->inlen)
longjmp(s->env, 1); /* out of input */
val |= (long)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */
s->bitcnt += 8;
}
Expand Down Expand Up @@ -162,15 +170,17 @@ local int stored(struct state *s)
s->bitcnt = 0;

/* get length and check against its one's complement */
if (s->incnt + 4 > s->inlen) return 2; /* not enough input */
if (s->incnt + 4 > s->inlen)
return 2; /* not enough input */
len = s->in[s->incnt++];
len |= s->in[s->incnt++] << 8;
if (s->in[s->incnt++] != (~len & 0xff) ||
s->in[s->incnt++] != ((~len >> 8) & 0xff))
return -2; /* didn't match complement! */

/* copy len bytes from in to out */
if (s->incnt + len > s->inlen) return 2; /* not enough input */
if (s->incnt + len > s->inlen)
return 2; /* not enough input */
if (s->out != NIL) {
if (s->outcnt + len > s->outlen)
return 1; /* not enough output space */
Expand Down Expand Up @@ -222,7 +232,7 @@ struct huffman {
* in the deflate format. See the format notes for fixed() and dynamic().
*/
#ifdef SLOW
local int decode(struct state *s, struct huffman *h)
local int decode(struct state *s, const struct huffman *h)
{
int len; /* current number of bits in code */
int code; /* len bits being decoded */
Expand Down Expand Up @@ -250,7 +260,7 @@ local int decode(struct state *s, struct huffman *h)
* a few percent larger.
*/
#else /* !SLOW */
local int decode(struct state *s, struct huffman *h)
local int decode(struct state *s, const struct huffman *h)
{
int len; /* current number of bits in code */
int code; /* len bits being decoded */
Expand Down Expand Up @@ -283,10 +293,13 @@ local int decode(struct state *s, struct huffman *h)
len++;
}
left = (MAXBITS+1) - len;
if (left == 0) break;
if (s->incnt == s->inlen) longjmp(s->env, 1); /* out of input */
if (left == 0)
break;
if (s->incnt == s->inlen)
longjmp(s->env, 1); /* out of input */
bitbuf = s->in[s->incnt++];
if (left > 8) left = 8;
if (left > 8)
left = 8;
}
return -10; /* ran out of codes */
}
Expand Down Expand Up @@ -324,7 +337,7 @@ local int decode(struct state *s, struct huffman *h)
* - Within a given code length, the symbols are kept in ascending order for
* the code bits definition.
*/
local int construct(struct huffman *h, short *length, int n)
local int construct(struct huffman *h, const short *length, int n)
{
int symbol; /* current symbol when stepping through length[] */
int len; /* current length when stepping through h->count[] */
Expand All @@ -344,7 +357,8 @@ local int construct(struct huffman *h, short *length, int n)
for (len = 1; len <= MAXBITS; len++) {
left <<= 1; /* one more bit, double codes left */
left -= h->count[len]; /* deduct count from possible codes */
if (left < 0) return left; /* over-subscribed--return negative */
if (left < 0)
return left; /* over-subscribed--return negative */
} /* left > 0 means incomplete */

/* generate offsets into symbol table for each length for sorting */
Expand Down Expand Up @@ -420,8 +434,8 @@ local int construct(struct huffman *h, short *length, int n)
* defined to do the wrong thing in this case.
*/
local int codes(struct state *s,
struct huffman *lencode,
struct huffman *distcode)
const struct huffman *lencode,
const struct huffman *distcode)
{
int symbol; /* decoded symbol */
int len; /* length for copy */
Expand All @@ -444,24 +458,28 @@ local int codes(struct state *s,
/* decode literals and length/distance pairs */
do {
symbol = decode(s, lencode);
if (symbol < 0) return symbol; /* invalid symbol */
if (symbol < 0)
return symbol; /* invalid symbol */
if (symbol < 256) { /* literal: symbol is the byte */
/* write out the literal */
if (s->out != NIL) {
if (s->outcnt == s->outlen) return 1;
if (s->outcnt == s->outlen)
return 1;
s->out[s->outcnt] = symbol;
}
s->outcnt++;
}
else if (symbol > 256) { /* length */
/* get and compute length */
symbol -= 257;
if (symbol >= 29) return -10; /* invalid fixed code */
if (symbol >= 29)
return -10; /* invalid fixed code */
len = lens[symbol] + bits(s, lext[symbol]);

/* get and check distance */
symbol = decode(s, distcode);
if (symbol < 0) return symbol; /* invalid symbol */
if (symbol < 0)
return symbol; /* invalid symbol */
dist = dists[symbol] + bits(s, dext[symbol]);
#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
if (dist > s->outcnt)
Expand All @@ -470,13 +488,15 @@ local int codes(struct state *s,

/* copy length bytes from distance bytes back */
if (s->out != NIL) {
if (s->outcnt + len > s->outlen) return 1;
if (s->outcnt + len > s->outlen)
return 1;
while (len--) {
s->out[s->outcnt] =
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
dist > s->outcnt ? 0 :
dist > s->outcnt ?
0 :
#endif
s->out[s->outcnt - dist];
s->out[s->outcnt - dist];
s->outcnt++;
}
}
Expand Down Expand Up @@ -525,6 +545,12 @@ local int fixed(struct state *s)
int symbol;
short lengths[FIXLCODES];

/* construct lencode and distcode */
lencode.count = lencnt;
lencode.symbol = lensym;
distcode.count = distcnt;
distcode.symbol = distsym;

/* literal/length table */
for (symbol = 0; symbol < 144; symbol++)
lengths[symbol] = 8;
Expand All @@ -541,12 +567,6 @@ local int fixed(struct state *s)
lengths[symbol] = 5;
construct(&distcode, lengths, MAXDCODES);

/* construct lencode and distcode */
lencode.count = lencnt;
lencode.symbol = lensym;
distcode.count = distcnt;
distcode.symbol = distsym;

/* do this just once */
virgin = 0;
}
Expand All @@ -573,10 +593,10 @@ local int fixed(struct state *s)
* provided for each of the literal/length symbols, and for each of the
* distance symbols.
*
* - If a symbol is not used in the block, this is represented by a zero as
* as the code length. This does not mean a zero-length code, but rather
* that no code should be created for this symbol. There is no way in the
* deflate format to represent a zero-length code.
* - If a symbol is not used in the block, this is represented by a zero as the
* code length. This does not mean a zero-length code, but rather that no
* code should be created for this symbol. There is no way in the deflate
* format to represent a zero-length code.
*
* - The maximum number of bits in a code is 15, so the possible lengths for
* any code are 1..15.
Expand Down Expand Up @@ -604,7 +624,7 @@ local int fixed(struct state *s)
* are themselves compressed using Huffman codes and run-length encoding. In
* the list of code lengths, a 0 symbol means no code, a 1..15 symbol means
* that length, and the symbols 16, 17, and 18 are run-length instructions.
* Each of 16, 17, and 18 are follwed by extra bits to define the length of
* Each of 16, 17, and 18 are followed by extra bits to define the length of
* the run. 16 copies the last length 3 to 6 times. 17 represents 3 to 10
* zero lengths, and 18 represents 11 to 138 zero lengths. Unused symbols
* are common, hence the special coding for zero lengths.
Expand Down Expand Up @@ -675,7 +695,8 @@ local int dynamic(struct state *s)

/* build huffman table for code lengths codes (use lencode temporarily) */
err = construct(&lencode, lengths, 19);
if (err != 0) return -4; /* require complete code set here */
if (err != 0) /* require complete code set here */
return -4;

/* read length/literal and distance code length tables */
index = 0;
Expand All @@ -684,12 +705,15 @@ local int dynamic(struct state *s)
int len; /* last length to repeat */

symbol = decode(s, &lencode);
if (symbol < 0)
return symbol; /* invalid symbol */
if (symbol < 16) /* length in 0..15 */
lengths[index++] = symbol;
else { /* repeat instruction */
len = 0; /* assume repeating zeros */
if (symbol == 16) { /* repeat last length 3..6 times */
if (index == 0) return -5; /* no last length! */
if (index == 0)
return -5; /* no last length! */
len = lengths[index - 1]; /* last length */
symbol = 3 + bits(s, 2);
}
Expand All @@ -710,13 +734,13 @@ local int dynamic(struct state *s)

/* build huffman table for literal/length codes */
err = construct(&lencode, lengths, nlen);
if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))
return -7; /* only allow incomplete codes if just one code */
if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))
return -7; /* incomplete code ok only for single length 1 code */

/* build huffman table for distance codes */
err = construct(&distcode, lengths + nlen, ndist);
if (err < 0 || (err > 0 && ndist - distcode.count[0] != 1))
return -8; /* only allow incomplete codes if just one code */
if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))
return -8; /* incomplete code ok only for single length 1 code */

/* decode data until end-of-block code */
return codes(s, &lencode, &distcode);
Expand Down Expand Up @@ -768,7 +792,7 @@ local int dynamic(struct state *s)
*/
int puff(unsigned char *dest, /* pointer to destination pointer */
unsigned long *destlen, /* amount of output space */
unsigned char *source, /* pointer to source data pointer */
const unsigned char *source, /* pointer to source data pointer */
unsigned long *sourcelen) /* amount of input available */
{
struct state s; /* input/output state */
Expand All @@ -795,11 +819,15 @@ int puff(unsigned char *dest, /* pointer to destination pointer */
do {
last = bits(&s, 1); /* one if last block */
type = bits(&s, 2); /* block type 0..3 */
err = type == 0 ? stored(&s) :
(type == 1 ? fixed(&s) :
(type == 2 ? dynamic(&s) :
-1)); /* type == 3, invalid */
if (err != 0) break; /* return with error */
err = type == 0 ?
stored(&s) :
(type == 1 ?
fixed(&s) :
(type == 2 ?
dynamic(&s) :
-1)); /* type == 3, invalid */
if (err != 0)
break; /* return with error */
} while (!last);
}

Expand Down
10 changes: 7 additions & 3 deletions source/lv1/puff/puff.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* puff.h
Copyright (C) 2002-2010 Mark Adler, all rights reserved
version 2.1, 4 Apr 2010
Copyright (C) 2002-2013 Mark Adler, all rights reserved
version 2.3, 21 Jan 2013

This software is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
Expand All @@ -25,7 +25,11 @@
/*
* See puff.c for purpose and usage.
*/
#ifndef NIL
# define NIL ((unsigned char *)0) /* for no output option */
#endif

int puff(unsigned char *dest, /* pointer to destination pointer */
unsigned long *destlen, /* amount of output space */
unsigned char *source, /* pointer to source data pointer */
const unsigned char *source, /* pointer to source data pointer */
unsigned long *sourcelen); /* amount of input available */