forked from premiere/premiere-libtorrent
update puff.c for gzip inflation (#1022)
update puff.c for gzip inflation
This commit is contained in:
parent
80e5ce9b32
commit
debf3c6e36
|
@ -1,5 +1,6 @@
|
||||||
1.1.1 release
|
1.1.1 release
|
||||||
|
|
||||||
|
* update puff.c for gzip inflation
|
||||||
* add dht_bootstrap_node a setting in settings_pack (and add default)
|
* add dht_bootstrap_node a setting in settings_pack (and add default)
|
||||||
* make pad-file and symlink support conform to BEP47
|
* make pad-file and symlink support conform to BEP47
|
||||||
* fix piece picker bug that could result in division by zero
|
* fix piece picker bug that could result in division by zero
|
||||||
|
|
|
@ -25,9 +25,7 @@
|
||||||
/*
|
/*
|
||||||
* See puff.c for purpose and usage.
|
* See puff.c for purpose and usage.
|
||||||
*/
|
*/
|
||||||
#include <boost/cstdint.hpp>
|
|
||||||
|
|
||||||
int puff(unsigned char *dest, /* pointer to destination pointer */
|
int puff(unsigned char *dest, /* pointer to destination pointer */
|
||||||
boost::uint32_t *destlen, /* amount of output space */
|
unsigned long *destlen, /* amount of output space */
|
||||||
const unsigned char *source, /* pointer to source data pointer */
|
const unsigned char *source, /* pointer to source data pointer */
|
||||||
boost::uint32_t *sourcelen); /* amount of input available */
|
unsigned long *sourcelen); /* amount of input available */
|
||||||
|
|
|
@ -212,9 +212,9 @@ namespace libtorrent
|
||||||
|
|
||||||
// start off with 4 kilobytes and grow
|
// start off with 4 kilobytes and grow
|
||||||
// if needed
|
// if needed
|
||||||
boost::uint32_t destlen = 4096;
|
unsigned long destlen = 4096;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
boost::uint32_t srclen = size - header_len;
|
unsigned long srclen = size - header_len;
|
||||||
in += header_len;
|
in += header_len;
|
||||||
|
|
||||||
do
|
do
|
||||||
|
|
283
src/puff.cpp
283
src/puff.cpp
|
@ -1,8 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* puff.c
|
* puff.c
|
||||||
* Copyright (C) 2002, 2003 Mark Adler
|
* Copyright (C) 2002-2013 Mark Adler
|
||||||
* For conditions of distribution and use, see copyright notice in puff.h
|
* For conditions of distribution and use, see copyright notice in puff.h
|
||||||
* version 1.7, 3 Mar 2003
|
* version 2.3, 21 Jan 2013
|
||||||
*
|
*
|
||||||
* puff.c is a simple inflate written to be an unambiguous way to specify the
|
* 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
|
* deflate format. It is not written for speed but rather simplicity. As a
|
||||||
|
@ -49,9 +49,9 @@
|
||||||
* - Fix fixed codes table error
|
* - Fix fixed codes table error
|
||||||
* - Provide a scanning mode for determining size of
|
* - Provide a scanning mode for determining size of
|
||||||
* uncompressed data
|
* 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 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
|
* - Use indexes instead of pointers for readability
|
||||||
* 1.4 31 Mar 2002 - Simplify construct() code set check
|
* 1.4 31 Mar 2002 - Simplify construct() code set check
|
||||||
* - Fix some comments
|
* - Fix some comments
|
||||||
|
@ -60,26 +60,33 @@
|
||||||
* 1.6 7 Aug 2002 - Minor format changes
|
* 1.6 7 Aug 2002 - Minor format changes
|
||||||
* 1.7 3 Mar 2003 - Added test code for distribution
|
* 1.7 3 Mar 2003 - Added test code for distribution
|
||||||
* - Added zlib-like license
|
* - Added zlib-like license
|
||||||
|
* 1.8 9 Jan 2004 - Added some comments on no distance codes case
|
||||||
|
* 1.9 21 Feb 2008 - Fix bug on 16-bit integer architectures [Pohland]
|
||||||
|
* - Catch missing end-of-block symbol error
|
||||||
|
* 2.0 25 Jul 2008 - Add #define to permit distance too far back
|
||||||
|
* - Add option in TEST code for puff to write the data
|
||||||
|
* - Add option in TEST code to skip input bytes
|
||||||
|
* - 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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
note by Arvid Norberg.
|
|
||||||
This file was turned into a .cpp file in order to
|
|
||||||
be able to take advantage of boost's cstdint.hpp file
|
|
||||||
All "short" has been replaced with boost::int16_t
|
|
||||||
and all "long" with boost::int32_t according to the
|
|
||||||
type width assuptions in the comment above.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// this whole file is just preserved and warnings are suppressed
|
// this whole file is just preserved and warnings are suppressed
|
||||||
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
#include "libtorrent/aux_/disable_warnings_push.hpp"
|
||||||
|
|
||||||
#include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */
|
#include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */
|
||||||
#include <boost/cstdint.hpp> /* for types with size guarantees */
|
#include <string.h> /* for NULL */
|
||||||
#include "libtorrent/puff.hpp" /* prototype for puff() */
|
#include "puff.hpp" /* prototype for puff() */
|
||||||
|
|
||||||
#define local static /* for local function definitions */
|
#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 --
|
* Maximums for allocations and loops. It is not useful to change these --
|
||||||
|
@ -95,13 +102,13 @@ type width assuptions in the comment above.
|
||||||
struct state {
|
struct state {
|
||||||
/* output state */
|
/* output state */
|
||||||
unsigned char *out; /* output buffer */
|
unsigned char *out; /* output buffer */
|
||||||
boost::uint32_t outlen; /* available space at out */
|
unsigned long outlen; /* available space at out */
|
||||||
boost::uint32_t outcnt; /* bytes written to out so far */
|
unsigned long outcnt; /* bytes written to out so far */
|
||||||
|
|
||||||
/* input state */
|
/* input state */
|
||||||
const unsigned char *in; /* input buffer */
|
const unsigned char *in; /* input buffer */
|
||||||
boost::uint32_t inlen; /* available input at in */
|
unsigned long inlen; /* available input at in */
|
||||||
boost::uint32_t incnt; /* bytes read so far */
|
unsigned long incnt; /* bytes read so far */
|
||||||
int bitbuf; /* bit buffer */
|
int bitbuf; /* bit buffer */
|
||||||
int bitcnt; /* number of bits in bit buffer */
|
int bitcnt; /* number of bits in bit buffer */
|
||||||
|
|
||||||
|
@ -122,22 +129,23 @@ struct state {
|
||||||
*/
|
*/
|
||||||
local int bits(struct state *s, int need)
|
local int bits(struct state *s, int need)
|
||||||
{
|
{
|
||||||
boost::int32_t val; /* bit accumulator (can use up to 20 bits) */
|
long val; /* bit accumulator (can use up to 20 bits) */
|
||||||
|
|
||||||
/* load at least need bits into val */
|
/* load at least need bits into val */
|
||||||
val = s->bitbuf;
|
val = s->bitbuf;
|
||||||
while (s->bitcnt < need) {
|
while (s->bitcnt < need) {
|
||||||
if (s->incnt == s->inlen) longjmp(s->env, 1); /* out of input */
|
if (s->incnt == s->inlen)
|
||||||
val |= (boost::int32_t)(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */
|
longjmp(s->env, 1); /* out of input */
|
||||||
|
val |= long(s->in[s->incnt++]) << s->bitcnt; /* load eight bits */
|
||||||
s->bitcnt += 8;
|
s->bitcnt += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* drop need bits and update buffer, always zero to seven bits left */
|
/* drop need bits and update buffer, always zero to seven bits left */
|
||||||
s->bitbuf = (int)(val >> need);
|
s->bitbuf = int(val >> need);
|
||||||
s->bitcnt -= need;
|
s->bitcnt -= need;
|
||||||
|
|
||||||
/* return need bits, zeroing the bits above that */
|
/* return need bits, zeroing the bits above that */
|
||||||
return (int)(val & ((1L << need) - 1));
|
return int(val & ((1L << need) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -166,7 +174,8 @@ local int stored(struct state *s)
|
||||||
s->bitcnt = 0;
|
s->bitcnt = 0;
|
||||||
|
|
||||||
/* get length and check against its one's complement */
|
/* 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++];
|
||||||
len |= s->in[s->incnt++] << 8;
|
len |= s->in[s->incnt++] << 8;
|
||||||
if (s->in[s->incnt++] != (~len & 0xff) ||
|
if (s->in[s->incnt++] != (~len & 0xff) ||
|
||||||
|
@ -174,8 +183,9 @@ local int stored(struct state *s)
|
||||||
return -2; /* didn't match complement! */
|
return -2; /* didn't match complement! */
|
||||||
|
|
||||||
/* copy len bytes from in to out */
|
/* copy len bytes from in to out */
|
||||||
if (s->incnt + len > s->inlen) return 2; /* not enough input */
|
if (s->incnt + len > s->inlen)
|
||||||
if (s->out != NIL) {
|
return 2; /* not enough input */
|
||||||
|
if (s->out != NULL) {
|
||||||
if (s->outcnt + len > s->outlen)
|
if (s->outcnt + len > s->outlen)
|
||||||
return 1; /* not enough output space */
|
return 1; /* not enough output space */
|
||||||
while (len--)
|
while (len--)
|
||||||
|
@ -198,15 +208,15 @@ local int stored(struct state *s)
|
||||||
* seen in the function decode() below.
|
* seen in the function decode() below.
|
||||||
*/
|
*/
|
||||||
struct huffman {
|
struct huffman {
|
||||||
boost::int16_t *count; /* number of symbols of each length */
|
short *count; /* number of symbols of each length */
|
||||||
boost::int16_t *symbol; /* canonically ordered symbols */
|
short *symbol; /* canonically ordered symbols */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Decode a code from the stream s using huffman table h. Return the symbol or
|
* Decode a code from the stream s using huffman table h. Return the symbol or
|
||||||
* a negative value if there is an error. If all of the lengths are zero, i.e.
|
* a negative value if there is an error. If all of the lengths are zero, i.e.
|
||||||
* an empty code, or if the code is incomplete and an invalid code is received,
|
* an empty code, or if the code is incomplete and an invalid code is received,
|
||||||
* then -9 is returned after reading MAXBITS bits.
|
* then -10 is returned after reading MAXBITS bits.
|
||||||
*
|
*
|
||||||
* Format notes:
|
* Format notes:
|
||||||
*
|
*
|
||||||
|
@ -226,7 +236,7 @@ struct huffman {
|
||||||
* in the deflate format. See the format notes for fixed() and dynamic().
|
* in the deflate format. See the format notes for fixed() and dynamic().
|
||||||
*/
|
*/
|
||||||
#ifdef SLOW
|
#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 len; /* current number of bits in code */
|
||||||
int code; /* len bits being decoded */
|
int code; /* len bits being decoded */
|
||||||
|
@ -238,14 +248,14 @@ local int decode(struct state *s, struct huffman *h)
|
||||||
for (len = 1; len <= MAXBITS; len++) {
|
for (len = 1; len <= MAXBITS; len++) {
|
||||||
code |= bits(s, 1); /* get next bit */
|
code |= bits(s, 1); /* get next bit */
|
||||||
count = h->count[len];
|
count = h->count[len];
|
||||||
if (code < first + count) /* if length len, return symbol */
|
if (code - count < first) /* if length len, return symbol */
|
||||||
return h->symbol[index + (code - first)];
|
return h->symbol[index + (code - first)];
|
||||||
index += count; /* else update for next length */
|
index += count; /* else update for next length */
|
||||||
first += count;
|
first += count;
|
||||||
first <<= 1;
|
first <<= 1;
|
||||||
code <<= 1;
|
code <<= 1;
|
||||||
}
|
}
|
||||||
return -9; /* ran out of codes */
|
return -10; /* ran out of codes */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -254,7 +264,7 @@ local int decode(struct state *s, struct huffman *h)
|
||||||
* a few percent larger.
|
* a few percent larger.
|
||||||
*/
|
*/
|
||||||
#else /* !SLOW */
|
#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 len; /* current number of bits in code */
|
||||||
int code; /* len bits being decoded */
|
int code; /* len bits being decoded */
|
||||||
|
@ -263,7 +273,7 @@ local int decode(struct state *s, struct huffman *h)
|
||||||
int index; /* index of first code of length len in symbol table */
|
int index; /* index of first code of length len in symbol table */
|
||||||
int bitbuf; /* bits from stream */
|
int bitbuf; /* bits from stream */
|
||||||
int left; /* bits left in next or left to process */
|
int left; /* bits left in next or left to process */
|
||||||
boost::int16_t *next; /* next number of codes */
|
short *next; /* next number of codes */
|
||||||
|
|
||||||
bitbuf = s->bitbuf;
|
bitbuf = s->bitbuf;
|
||||||
left = s->bitcnt;
|
left = s->bitcnt;
|
||||||
|
@ -275,7 +285,7 @@ local int decode(struct state *s, struct huffman *h)
|
||||||
code |= bitbuf & 1;
|
code |= bitbuf & 1;
|
||||||
bitbuf >>= 1;
|
bitbuf >>= 1;
|
||||||
count = *next++;
|
count = *next++;
|
||||||
if (code < first + count) { /* if length len, return symbol */
|
if (code - count < first) { /* if length len, return symbol */
|
||||||
s->bitbuf = bitbuf;
|
s->bitbuf = bitbuf;
|
||||||
s->bitcnt = (s->bitcnt - len) & 7;
|
s->bitcnt = (s->bitcnt - len) & 7;
|
||||||
return h->symbol[index + (code - first)];
|
return h->symbol[index + (code - first)];
|
||||||
|
@ -287,12 +297,15 @@ local int decode(struct state *s, struct huffman *h)
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
left = (MAXBITS+1) - len;
|
left = (MAXBITS+1) - len;
|
||||||
if (left == 0) break;
|
if (left == 0)
|
||||||
if (s->incnt == s->inlen) longjmp(s->env, 1); /* out of input */
|
break;
|
||||||
|
if (s->incnt == s->inlen)
|
||||||
|
longjmp(s->env, 1); /* out of input */
|
||||||
bitbuf = s->in[s->incnt++];
|
bitbuf = s->in[s->incnt++];
|
||||||
if (left > 8) left = 8;
|
if (left > 8)
|
||||||
|
left = 8;
|
||||||
}
|
}
|
||||||
return -9; /* ran out of codes */
|
return -10; /* ran out of codes */
|
||||||
}
|
}
|
||||||
#endif /* SLOW */
|
#endif /* SLOW */
|
||||||
|
|
||||||
|
@ -328,12 +341,12 @@ local int decode(struct state *s, struct huffman *h)
|
||||||
* - Within a given code length, the symbols are kept in ascending order for
|
* - Within a given code length, the symbols are kept in ascending order for
|
||||||
* the code bits definition.
|
* the code bits definition.
|
||||||
*/
|
*/
|
||||||
local int construct(struct huffman *h, boost::int16_t *length, int n)
|
local int construct(struct huffman *h, const short *length, int n)
|
||||||
{
|
{
|
||||||
int symbol; /* current symbol when stepping through length[] */
|
int symbol; /* current symbol when stepping through length[] */
|
||||||
int len; /* current length when stepping through h->count[] */
|
int len; /* current length when stepping through h->count[] */
|
||||||
int left; /* number of possible codes left of current length */
|
int left; /* number of possible codes left of current length */
|
||||||
boost::int16_t offs[MAXBITS+1]; /* offsets in symbol table for each length */
|
short offs[MAXBITS+1]; /* offsets in symbol table for each length */
|
||||||
|
|
||||||
/* count number of codes of each length */
|
/* count number of codes of each length */
|
||||||
for (len = 0; len <= MAXBITS; len++)
|
for (len = 0; len <= MAXBITS; len++)
|
||||||
|
@ -348,7 +361,8 @@ local int construct(struct huffman *h, boost::int16_t *length, int n)
|
||||||
for (len = 1; len <= MAXBITS; len++) {
|
for (len = 1; len <= MAXBITS; len++) {
|
||||||
left <<= 1; /* one more bit, double codes left */
|
left <<= 1; /* one more bit, double codes left */
|
||||||
left -= h->count[len]; /* deduct count from possible codes */
|
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 */
|
} /* left > 0 means incomplete */
|
||||||
|
|
||||||
/* generate offsets into symbol table for each length for sorting */
|
/* generate offsets into symbol table for each length for sorting */
|
||||||
|
@ -424,23 +438,23 @@ local int construct(struct huffman *h, boost::int16_t *length, int n)
|
||||||
* defined to do the wrong thing in this case.
|
* defined to do the wrong thing in this case.
|
||||||
*/
|
*/
|
||||||
local int codes(struct state *s,
|
local int codes(struct state *s,
|
||||||
struct huffman *lencode,
|
const struct huffman *lencode,
|
||||||
struct huffman *distcode)
|
const struct huffman *distcode)
|
||||||
{
|
{
|
||||||
int symbol; /* decoded symbol */
|
int symbol; /* decoded symbol */
|
||||||
int len; /* length for copy */
|
int len; /* length for copy */
|
||||||
unsigned dist; /* distance for copy */
|
unsigned dist; /* distance for copy */
|
||||||
static const boost::int16_t lens[29] = { /* Size base for length codes 257..285 */
|
static const short lens[29] = { /* Size base for length codes 257..285 */
|
||||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
|
||||||
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
|
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
|
||||||
static const boost::int16_t lext[29] = { /* Extra bits for length codes 257..285 */
|
static const short lext[29] = { /* Extra bits for length codes 257..285 */
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
|
||||||
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
|
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
|
||||||
static const boost::int16_t dists[30] = { /* Offset base for distance codes 0..29 */
|
static const short dists[30] = { /* Offset base for distance codes 0..29 */
|
||||||
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
|
||||||
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
|
||||||
8193, 12289, 16385, 24577};
|
8193, 12289, 16385, 24577};
|
||||||
static const boost::int16_t dext[30] = { /* Extra bits for distance codes 0..29 */
|
static const short dext[30] = { /* Extra bits for distance codes 0..29 */
|
||||||
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
|
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
|
||||||
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
|
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
|
||||||
12, 12, 13, 13};
|
12, 12, 13, 13};
|
||||||
|
@ -448,11 +462,13 @@ local int codes(struct state *s,
|
||||||
/* decode literals and length/distance pairs */
|
/* decode literals and length/distance pairs */
|
||||||
do {
|
do {
|
||||||
symbol = decode(s, lencode);
|
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 */
|
if (symbol < 256) { /* literal: symbol is the byte */
|
||||||
/* write out the literal */
|
/* write out the literal */
|
||||||
if (s->out != NIL) {
|
if (s->out != NULL) {
|
||||||
if (s->outcnt == s->outlen) return 1;
|
if (s->outcnt == s->outlen)
|
||||||
|
return 1;
|
||||||
s->out[s->outcnt] = symbol;
|
s->out[s->outcnt] = symbol;
|
||||||
}
|
}
|
||||||
s->outcnt++;
|
s->outcnt++;
|
||||||
|
@ -460,21 +476,31 @@ local int codes(struct state *s,
|
||||||
else if (symbol > 256) { /* length */
|
else if (symbol > 256) { /* length */
|
||||||
/* get and compute length */
|
/* get and compute length */
|
||||||
symbol -= 257;
|
symbol -= 257;
|
||||||
if (symbol >= 29) return -9; /* invalid fixed code */
|
if (symbol >= 29)
|
||||||
|
return -10; /* invalid fixed code */
|
||||||
len = lens[symbol] + bits(s, lext[symbol]);
|
len = lens[symbol] + bits(s, lext[symbol]);
|
||||||
|
|
||||||
/* get and check distance */
|
/* get and check distance */
|
||||||
symbol = decode(s, distcode);
|
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]);
|
dist = dists[symbol] + bits(s, dext[symbol]);
|
||||||
|
#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
|
||||||
if (dist > s->outcnt)
|
if (dist > s->outcnt)
|
||||||
return -10; /* distance too far back */
|
return -11; /* distance too far back */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* copy length bytes from distance bytes back */
|
/* copy length bytes from distance bytes back */
|
||||||
if (s->out != NIL) {
|
if (s->out != NULL) {
|
||||||
if (s->outcnt + len > s->outlen) return 1;
|
if (s->outcnt + len > s->outlen)
|
||||||
|
return 1;
|
||||||
while (len--) {
|
while (len--) {
|
||||||
s->out[s->outcnt] = s->out[s->outcnt - dist];
|
s->out[s->outcnt] =
|
||||||
|
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
|
||||||
|
dist > s->outcnt ?
|
||||||
|
0 :
|
||||||
|
#endif
|
||||||
|
s->out[s->outcnt - dist];
|
||||||
s->outcnt++;
|
s->outcnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -514,15 +540,20 @@ local int codes(struct state *s,
|
||||||
local int fixed(struct state *s)
|
local int fixed(struct state *s)
|
||||||
{
|
{
|
||||||
static int virgin = 1;
|
static int virgin = 1;
|
||||||
static boost::int16_t lencnt[MAXBITS+1], lensym[FIXLCODES];
|
static short lencnt[MAXBITS+1], lensym[FIXLCODES];
|
||||||
static boost::int16_t distcnt[MAXBITS+1], distsym[MAXDCODES];
|
static short distcnt[MAXBITS+1], distsym[MAXDCODES];
|
||||||
static struct huffman lencode = {lencnt, lensym};
|
static struct huffman lencode, distcode;
|
||||||
static struct huffman distcode = {distcnt, distsym};
|
|
||||||
|
|
||||||
/* build fixed huffman tables if first call (may not be thread safe) */
|
/* build fixed huffman tables if first call (may not be thread safe) */
|
||||||
if (virgin) {
|
if (virgin) {
|
||||||
int symbol;
|
int symbol;
|
||||||
boost::int16_t lengths[FIXLCODES];
|
short lengths[FIXLCODES];
|
||||||
|
|
||||||
|
/* construct lencode and distcode */
|
||||||
|
lencode.count = lencnt;
|
||||||
|
lencode.symbol = lensym;
|
||||||
|
distcode.count = distcnt;
|
||||||
|
distcode.symbol = distsym;
|
||||||
|
|
||||||
/* literal/length table */
|
/* literal/length table */
|
||||||
for (symbol = 0; symbol < 144; symbol++)
|
for (symbol = 0; symbol < 144; symbol++)
|
||||||
|
@ -590,6 +621,9 @@ local int fixed(struct state *s)
|
||||||
* block is fewer bits), but it is allowed by the format. So incomplete
|
* block is fewer bits), but it is allowed by the format. So incomplete
|
||||||
* literal/length codes of one symbol should also be permitted.
|
* literal/length codes of one symbol should also be permitted.
|
||||||
*
|
*
|
||||||
|
* - If there are only literal codes and no lengths, then there are no distance
|
||||||
|
* codes. This is represented by one distance code with zero bits.
|
||||||
|
*
|
||||||
* - The list of up to 286 length/literal lengths and up to 30 distance lengths
|
* - The list of up to 286 length/literal lengths and up to 30 distance lengths
|
||||||
* are themselves compressed using Huffman codes and run-length encoding. In
|
* 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
|
* the list of code lengths, a 0 symbol means no code, a 1..15 symbol means
|
||||||
|
@ -637,14 +671,19 @@ local int dynamic(struct state *s)
|
||||||
int nlen, ndist, ncode; /* number of lengths in descriptor */
|
int nlen, ndist, ncode; /* number of lengths in descriptor */
|
||||||
int index; /* index of lengths[] */
|
int index; /* index of lengths[] */
|
||||||
int err; /* construct() return value */
|
int err; /* construct() return value */
|
||||||
boost::int16_t lengths[MAXCODES]; /* descriptor code lengths */
|
short lengths[MAXCODES]; /* descriptor code lengths */
|
||||||
boost::int16_t lencnt[MAXBITS+1], lensym[MAXLCODES]; /* lencode memory */
|
short lencnt[MAXBITS+1], lensym[MAXLCODES]; /* lencode memory */
|
||||||
boost::int16_t distcnt[MAXBITS+1], distsym[MAXDCODES]; /* distcode memory */
|
short distcnt[MAXBITS+1], distsym[MAXDCODES]; /* distcode memory */
|
||||||
struct huffman lencode = {lencnt, lensym}; /* length code */
|
struct huffman lencode, distcode; /* length and distance codes */
|
||||||
struct huffman distcode = {distcnt, distsym}; /* distance code */
|
static const short order[19] = /* permutation of code length codes */
|
||||||
static const boost::int16_t order[19] = /* permutation of code length codes */
|
|
||||||
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
|
||||||
|
|
||||||
|
/* construct lencode and distcode */
|
||||||
|
lencode.count = lencnt;
|
||||||
|
lencode.symbol = lensym;
|
||||||
|
distcode.count = distcnt;
|
||||||
|
distcode.symbol = distsym;
|
||||||
|
|
||||||
/* get number of lengths in each table, check lengths */
|
/* get number of lengths in each table, check lengths */
|
||||||
nlen = bits(s, 5) + 257;
|
nlen = bits(s, 5) + 257;
|
||||||
ndist = bits(s, 5) + 1;
|
ndist = bits(s, 5) + 1;
|
||||||
|
@ -660,7 +699,8 @@ local int dynamic(struct state *s)
|
||||||
|
|
||||||
/* build huffman table for code lengths codes (use lencode temporarily) */
|
/* build huffman table for code lengths codes (use lencode temporarily) */
|
||||||
err = construct(&lencode, lengths, 19);
|
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 */
|
/* read length/literal and distance code length tables */
|
||||||
index = 0;
|
index = 0;
|
||||||
|
@ -669,12 +709,15 @@ local int dynamic(struct state *s)
|
||||||
int len; /* last length to repeat */
|
int len; /* last length to repeat */
|
||||||
|
|
||||||
symbol = decode(s, &lencode);
|
symbol = decode(s, &lencode);
|
||||||
|
if (symbol < 0)
|
||||||
|
return symbol; /* invalid symbol */
|
||||||
if (symbol < 16) /* length in 0..15 */
|
if (symbol < 16) /* length in 0..15 */
|
||||||
lengths[index++] = symbol;
|
lengths[index++] = symbol;
|
||||||
else { /* repeat instruction */
|
else { /* repeat instruction */
|
||||||
len = 0; /* assume repeating zeros */
|
len = 0; /* assume repeating zeros */
|
||||||
if (symbol == 16) { /* repeat last length 3..6 times */
|
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 */
|
len = lengths[index - 1]; /* last length */
|
||||||
symbol = 3 + bits(s, 2);
|
symbol = 3 + bits(s, 2);
|
||||||
}
|
}
|
||||||
|
@ -689,15 +732,19 @@ local int dynamic(struct state *s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check for end-of-block code -- there better be one! */
|
||||||
|
if (lengths[256] == 0)
|
||||||
|
return -9;
|
||||||
|
|
||||||
/* build huffman table for literal/length codes */
|
/* build huffman table for literal/length codes */
|
||||||
err = construct(&lencode, lengths, nlen);
|
err = construct(&lencode, lengths, nlen);
|
||||||
if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1))
|
if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))
|
||||||
return -7; /* only allow incomplete codes if just one code */
|
return -7; /* incomplete code ok only for single length 1 code */
|
||||||
|
|
||||||
/* build huffman table for distance codes */
|
/* build huffman table for distance codes */
|
||||||
err = construct(&distcode, lengths + nlen, ndist);
|
err = construct(&distcode, lengths + nlen, ndist);
|
||||||
if (err < 0 || (err > 0 && ndist - distcode.count[0] != 1))
|
if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))
|
||||||
return -8; /* only allow incomplete codes if just one code */
|
return -8; /* incomplete code ok only for single length 1 code */
|
||||||
|
|
||||||
/* decode data until end-of-block code */
|
/* decode data until end-of-block code */
|
||||||
return codes(s, &lencode, &distcode);
|
return codes(s, &lencode, &distcode);
|
||||||
|
@ -733,8 +780,9 @@ local int dynamic(struct state *s)
|
||||||
* -6: dynamic block code description: repeat more than specified lengths
|
* -6: dynamic block code description: repeat more than specified lengths
|
||||||
* -7: dynamic block code description: invalid literal/length code lengths
|
* -7: dynamic block code description: invalid literal/length code lengths
|
||||||
* -8: dynamic block code description: invalid distance code lengths
|
* -8: dynamic block code description: invalid distance code lengths
|
||||||
* -9: invalid literal/length or distance code in fixed or dynamic block
|
* -9: dynamic block code description: missing end-of-block code
|
||||||
* -10: distance is too far back in fixed or dynamic block
|
* -10: invalid literal/length or distance code in fixed or dynamic block
|
||||||
|
* -11: distance is too far back in fixed or dynamic block
|
||||||
*
|
*
|
||||||
* Format notes:
|
* Format notes:
|
||||||
*
|
*
|
||||||
|
@ -747,9 +795,9 @@ local int dynamic(struct state *s)
|
||||||
* expected values to check.
|
* expected values to check.
|
||||||
*/
|
*/
|
||||||
int puff(unsigned char *dest, /* pointer to destination pointer */
|
int puff(unsigned char *dest, /* pointer to destination pointer */
|
||||||
boost::uint32_t *destlen, /* amount of output space */
|
unsigned long *destlen, /* amount of output space */
|
||||||
const unsigned char *source, /* pointer to source data pointer */
|
const unsigned char *source, /* pointer to source data pointer */
|
||||||
boost::uint32_t *sourcelen) /* amount of input available */
|
unsigned long *sourcelen) /* amount of input available */
|
||||||
{
|
{
|
||||||
struct state s; /* input/output state */
|
struct state s; /* input/output state */
|
||||||
int last, type; /* block information */
|
int last, type; /* block information */
|
||||||
|
@ -775,11 +823,15 @@ int puff(unsigned char *dest, /* pointer to destination pointer */
|
||||||
do {
|
do {
|
||||||
last = bits(&s, 1); /* one if last block */
|
last = bits(&s, 1); /* one if last block */
|
||||||
type = bits(&s, 2); /* block type 0..3 */
|
type = bits(&s, 2); /* block type 0..3 */
|
||||||
err = type == 0 ? stored(&s) :
|
err = type == 0 ?
|
||||||
(type == 1 ? fixed(&s) :
|
stored(&s) :
|
||||||
(type == 2 ? dynamic(&s) :
|
(type == 1 ?
|
||||||
-1)); /* type == 3, invalid */
|
fixed(&s) :
|
||||||
if (err != 0) break; /* return with error */
|
(type == 2 ?
|
||||||
|
dynamic(&s) :
|
||||||
|
-1)); /* type == 3, invalid */
|
||||||
|
if (err != 0)
|
||||||
|
break; /* return with error */
|
||||||
} while (!last);
|
} while (!last);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -790,60 +842,3 @@ int puff(unsigned char *dest, /* pointer to destination pointer */
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST
|
|
||||||
/* Example of how to use puff() */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
local unsigned char *yank(char *name, boost::uint32_t *len)
|
|
||||||
{
|
|
||||||
boost::uint32_t size;
|
|
||||||
unsigned char *buf;
|
|
||||||
FILE *in;
|
|
||||||
struct stat s;
|
|
||||||
|
|
||||||
*len = 0;
|
|
||||||
if (stat(name, &s)) return NULL;
|
|
||||||
if ((s.st_mode & S_IFMT) != S_IFREG) return NULL;
|
|
||||||
size = (boost::uint32_t)(s.st_size);
|
|
||||||
if (size == 0 || (off_t)size != s.st_size) return NULL;
|
|
||||||
in = fopen(name, "r");
|
|
||||||
if (in == NULL) return NULL;
|
|
||||||
buf = malloc(size);
|
|
||||||
if (buf != NULL && fread(buf, 1, size, in) != size) {
|
|
||||||
free(buf);
|
|
||||||
buf = NULL;
|
|
||||||
}
|
|
||||||
fclose(in);
|
|
||||||
*len = size;
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
unsigned char *source;
|
|
||||||
boost::uint32_t len, sourcelen, destlen;
|
|
||||||
|
|
||||||
if (argc < 2) return 2;
|
|
||||||
source = yank(argv[1], &len);
|
|
||||||
if (source == NULL) return 2;
|
|
||||||
sourcelen = len;
|
|
||||||
ret = puff(NIL, &destlen, source, &sourcelen);
|
|
||||||
if (ret)
|
|
||||||
printf("puff() failed with return code %d\n", ret);
|
|
||||||
else {
|
|
||||||
printf("puff() succeeded uncompressing %lu bytes\n", destlen);
|
|
||||||
if (sourcelen < len) printf("%lu compressed bytes unused\n",
|
|
||||||
len - sourcelen);
|
|
||||||
}
|
|
||||||
free(source);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "libtorrent/aux_/disable_warnings_pop.hpp"
|
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,6 @@ test-suite libtorrent :
|
||||||
test_socket_io.cpp
|
test_socket_io.cpp
|
||||||
# test_random.cpp
|
# test_random.cpp
|
||||||
test_utf8.cpp
|
test_utf8.cpp
|
||||||
test_gzip.cpp
|
|
||||||
test_bitfield.cpp
|
test_bitfield.cpp
|
||||||
test_part_file.cpp
|
test_part_file.cpp
|
||||||
test_peer_list.cpp
|
test_peer_list.cpp
|
||||||
|
@ -123,6 +122,7 @@ test-suite libtorrent :
|
||||||
test_linked_list.cpp
|
test_linked_list.cpp
|
||||||
test_file_progress.cpp ]
|
test_file_progress.cpp ]
|
||||||
|
|
||||||
|
[ run test_gzip.cpp ]
|
||||||
[ run test_receive_buffer.cpp ]
|
[ run test_receive_buffer.cpp ]
|
||||||
[ run test_alert_manager.cpp ]
|
[ run test_alert_manager.cpp ]
|
||||||
[ run test_direct_dht.cpp ]
|
[ run test_direct_dht.cpp ]
|
||||||
|
@ -188,6 +188,7 @@ alias win-tests :
|
||||||
test_resume
|
test_resume
|
||||||
test_tracker
|
test_tracker
|
||||||
test_checking
|
test_checking
|
||||||
|
test_gzip
|
||||||
;
|
;
|
||||||
|
|
||||||
# the openssl test hangs on the travis osx machine. difficult to debug
|
# the openssl test hangs on the travis osx machine. difficult to debug
|
||||||
|
@ -227,6 +228,7 @@ alias osx-tests :
|
||||||
test_time_critical
|
test_time_critical
|
||||||
test_pex
|
test_pex
|
||||||
test_priority
|
test_priority
|
||||||
|
test_gzip
|
||||||
;
|
;
|
||||||
|
|
||||||
explicit win-tests ;
|
explicit win-tests ;
|
||||||
|
|
|
@ -115,6 +115,7 @@ EXTRA_DIST = Jamfile \
|
||||||
mutable_test_torrents/test3.torrent \
|
mutable_test_torrents/test3.torrent \
|
||||||
mutable_test_torrents/test3_pad_files.torrent \
|
mutable_test_torrents/test3_pad_files.torrent \
|
||||||
zeroes.gz \
|
zeroes.gz \
|
||||||
|
corrupt.gz \
|
||||||
utf8_test.txt \
|
utf8_test.txt \
|
||||||
web_server.py \
|
web_server.py \
|
||||||
socks.py \
|
socks.py \
|
||||||
|
|
Binary file not shown.
|
@ -38,7 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
using namespace libtorrent;
|
using namespace libtorrent;
|
||||||
|
|
||||||
TORRENT_TEST(gzip)
|
TORRENT_TEST(zeroes)
|
||||||
{
|
{
|
||||||
std::vector<char> zipped;
|
std::vector<char> zipped;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
|
@ -59,3 +59,19 @@ TORRENT_TEST(gzip)
|
||||||
TEST_EQUAL(inflated[i], 0);
|
TEST_EQUAL(inflated[i], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(corrupt)
|
||||||
|
{
|
||||||
|
std::vector<char> zipped;
|
||||||
|
error_code ec;
|
||||||
|
load_file(combine_path("..", "corrupt.gz"), zipped, ec, 1000000);
|
||||||
|
if (ec) fprintf(stderr, "failed to open file: (%d) %s\n", ec.value()
|
||||||
|
, ec.message().c_str());
|
||||||
|
TEST_CHECK(!ec);
|
||||||
|
|
||||||
|
std::vector<char> inflated;
|
||||||
|
inflate_gzip(&zipped[0], zipped.size(), inflated, 1000000, ec);
|
||||||
|
|
||||||
|
// we expect this to fail
|
||||||
|
TEST_CHECK(ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue