mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
The Zlib module now uses dynamically allocated contexts. I think
that completes the static-removal in the crypto library. Ooh. [originally from svn r2136]
This commit is contained in:
parent
db7196c174
commit
5df8e45c2e
60
ssh.c
60
ssh.c
@ -401,23 +401,27 @@ const static struct ssh_mac *buggymacs[] = {
|
||||
&ssh_sha1_buggy, &ssh_md5, &ssh_mac_none
|
||||
};
|
||||
|
||||
static void ssh_comp_none_init(void)
|
||||
static void *ssh_comp_none_init(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static void ssh_comp_none_cleanup(void *handle)
|
||||
{
|
||||
}
|
||||
static int ssh_comp_none_block(unsigned char *block, int len,
|
||||
static int ssh_comp_none_block(void *handle, unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int ssh_comp_none_disable(void)
|
||||
static int ssh_comp_none_disable(void *handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
const static struct ssh_compress ssh_comp_none = {
|
||||
"none",
|
||||
ssh_comp_none_init, ssh_comp_none_block,
|
||||
ssh_comp_none_init, ssh_comp_none_block,
|
||||
ssh_comp_none_disable
|
||||
ssh_comp_none_init, ssh_comp_none_cleanup, ssh_comp_none_block,
|
||||
ssh_comp_none_init, ssh_comp_none_cleanup, ssh_comp_none_block,
|
||||
ssh_comp_none_disable, NULL
|
||||
};
|
||||
extern const struct ssh_compress ssh_zlib;
|
||||
const static struct ssh_compress *compressions[] = {
|
||||
@ -566,6 +570,7 @@ struct ssh_tag {
|
||||
const struct ssh_mac *csmac, *scmac;
|
||||
void *cs_mac_ctx, *sc_mac_ctx;
|
||||
const struct ssh_compress *cscomp, *sccomp;
|
||||
void *cs_comp_ctx, *sc_comp_ctx;
|
||||
const struct ssh_kex *kex;
|
||||
const struct ssh_signkey *hostkey;
|
||||
unsigned char v2_session_id[20];
|
||||
@ -832,7 +837,8 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
|
||||
if (ssh->v1_compressing) {
|
||||
unsigned char *decompblk;
|
||||
int decomplen;
|
||||
zlib_decompress_block(ssh->pktin.body - 1, ssh->pktin.length + 1,
|
||||
zlib_decompress_block(ssh->sc_comp_ctx,
|
||||
ssh->pktin.body - 1, ssh->pktin.length + 1,
|
||||
&decompblk, &decomplen);
|
||||
|
||||
if (ssh->pktin.maxlen < st->pad + decomplen) {
|
||||
@ -1006,7 +1012,8 @@ static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
|
||||
unsigned char *newpayload;
|
||||
int newlen;
|
||||
if (ssh->sccomp &&
|
||||
ssh->sccomp->decompress(ssh->pktin.data + 5, ssh->pktin.length - 5,
|
||||
ssh->sccomp->decompress(ssh->sc_comp_ctx,
|
||||
ssh->pktin.data + 5, ssh->pktin.length - 5,
|
||||
&newpayload, &newlen)) {
|
||||
if (ssh->pktin.maxlen < newlen + 5) {
|
||||
ssh->pktin.maxlen = newlen + 5;
|
||||
@ -1171,7 +1178,8 @@ static int s_wrpkt_prepare(Ssh ssh)
|
||||
if (ssh->v1_compressing) {
|
||||
unsigned char *compblk;
|
||||
int complen;
|
||||
zlib_compress_block(ssh->pktout.body - 1, ssh->pktout.length + 1,
|
||||
zlib_compress_block(ssh->cs_comp_ctx,
|
||||
ssh->pktout.body - 1, ssh->pktout.length + 1,
|
||||
&compblk, &complen);
|
||||
ssh1_pktout_size(ssh, complen - 1);
|
||||
memcpy(ssh->pktout.body - 1, compblk, complen);
|
||||
@ -1457,7 +1465,8 @@ static int ssh2_pkt_construct(Ssh ssh)
|
||||
unsigned char *newpayload;
|
||||
int newlen;
|
||||
if (ssh->cscomp &&
|
||||
ssh->cscomp->compress(ssh->pktout.data + 5, ssh->pktout.length - 5,
|
||||
ssh->cscomp->compress(ssh->cs_comp_ctx, ssh->pktout.data + 5,
|
||||
ssh->pktout.length - 5,
|
||||
&newpayload, &newlen)) {
|
||||
ssh->pktout.length = 5;
|
||||
ssh2_pkt_adddata(ssh, newpayload, newlen);
|
||||
@ -3191,8 +3200,10 @@ static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt)
|
||||
}
|
||||
logevent("Started compression");
|
||||
ssh->v1_compressing = TRUE;
|
||||
zlib_compress_init();
|
||||
zlib_decompress_init();
|
||||
ssh->cs_comp_ctx = zlib_compress_init();
|
||||
logevent("Initialised zlib (RFC1950) compression");
|
||||
ssh->sc_comp_ctx = zlib_decompress_init();
|
||||
logevent("Initialised zlib (RFC1950) decompression");
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4064,10 +4075,16 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
|
||||
ssh->scmac = s->scmac_tobe;
|
||||
ssh->sc_mac_ctx = ssh->scmac->make_context();
|
||||
|
||||
if (ssh->cs_comp_ctx)
|
||||
ssh->cscomp->compress_cleanup(ssh->cs_comp_ctx);
|
||||
ssh->cscomp = s->cscomp_tobe;
|
||||
ssh->cs_comp_ctx = ssh->cscomp->compress_init();
|
||||
|
||||
if (ssh->sc_comp_ctx)
|
||||
ssh->sccomp->decompress_cleanup(ssh->sc_comp_ctx);
|
||||
ssh->sccomp = s->sccomp_tobe;
|
||||
ssh->cscomp->compress_init();
|
||||
ssh->sccomp->decompress_init();
|
||||
ssh->sc_comp_ctx = ssh->sccomp->decompress_init();
|
||||
|
||||
/*
|
||||
* Set IVs after keys. Here we use the exchange hash from the
|
||||
* _first_ key exchange.
|
||||
@ -4098,6 +4115,16 @@ static int do_ssh2_transport(Ssh ssh, unsigned char *in, int inlen, int ispkt)
|
||||
sprintf(buf, "Initialised %.200s server->client encryption",
|
||||
ssh->sccipher->text_name);
|
||||
logevent(buf);
|
||||
if (ssh->cscomp->text_name) {
|
||||
sprintf(buf, "Initialised %.200s compression",
|
||||
ssh->cscomp->text_name);
|
||||
logevent(buf);
|
||||
}
|
||||
if (ssh->sccomp->text_name) {
|
||||
sprintf(buf, "Initialised %.200s decompression",
|
||||
ssh->sccomp->text_name);
|
||||
logevent(buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4926,7 +4953,8 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
|
||||
* bytes we should adjust our string length
|
||||
* by.
|
||||
*/
|
||||
stringlen -= ssh->cscomp->disable_compression();
|
||||
stringlen -=
|
||||
ssh->cscomp->disable_compression(ssh->cs_comp_ctx);
|
||||
}
|
||||
ssh2_pkt_init(ssh, SSH2_MSG_IGNORE);
|
||||
ssh2_pkt_addstring_start(ssh);
|
||||
@ -5817,7 +5845,9 @@ static char *ssh_init(void *frontend_handle, void **backend_handle,
|
||||
ssh->scmac = NULL;
|
||||
ssh->sc_mac_ctx = NULL;
|
||||
ssh->cscomp = NULL;
|
||||
ssh->cs_comp_ctx = NULL;
|
||||
ssh->sccomp = NULL;
|
||||
ssh->sc_comp_ctx = NULL;
|
||||
ssh->kex = NULL;
|
||||
ssh->hostkey = NULL;
|
||||
ssh->exitcode = -1;
|
||||
|
23
ssh.h
23
ssh.h
@ -195,13 +195,16 @@ struct ssh_signkey {
|
||||
|
||||
struct ssh_compress {
|
||||
char *name;
|
||||
void (*compress_init) (void);
|
||||
int (*compress) (unsigned char *block, int len,
|
||||
void *(*compress_init) (void);
|
||||
void (*compress_cleanup) (void *);
|
||||
int (*compress) (void *, unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen);
|
||||
void (*decompress_init) (void);
|
||||
int (*decompress) (unsigned char *block, int len,
|
||||
void *(*decompress_init) (void);
|
||||
void (*decompress_cleanup) (void *);
|
||||
int (*decompress) (void *, unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen);
|
||||
int (*disable_compression) (void);
|
||||
int (*disable_compression) (void *);
|
||||
char *text_name;
|
||||
};
|
||||
|
||||
struct ssh2_userkey {
|
||||
@ -359,11 +362,13 @@ Bignum primegen(int bits, int modulus, int residue, Bignum factor,
|
||||
/*
|
||||
* zlib compression.
|
||||
*/
|
||||
void zlib_compress_init(void);
|
||||
void zlib_decompress_init(void);
|
||||
int zlib_compress_block(unsigned char *block, int len,
|
||||
void *zlib_compress_init(void);
|
||||
void zlib_compress_cleanup(void *);
|
||||
void *zlib_decompress_init(void);
|
||||
void zlib_decompress_cleanup(void *);
|
||||
int zlib_compress_block(void *, unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen);
|
||||
int zlib_decompress_block(unsigned char *block, int len,
|
||||
int zlib_decompress_block(void *, unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen);
|
||||
|
||||
/*
|
||||
|
285
sshzlib.c
285
sshzlib.c
@ -337,8 +337,6 @@ static void lz77_compress(struct LZ77Context *ctx,
|
||||
* having to transmit the trees.
|
||||
*/
|
||||
|
||||
static struct LZ77Context ectx;
|
||||
|
||||
struct Outbuf {
|
||||
unsigned char *outbuf;
|
||||
int outlen, outsize;
|
||||
@ -582,21 +580,28 @@ static void zlib_match(struct LZ77Context *ectx, int distance, int len)
|
||||
}
|
||||
}
|
||||
|
||||
void zlib_compress_init(void)
|
||||
void *zlib_compress_init(void)
|
||||
{
|
||||
struct Outbuf *out;
|
||||
struct LZ77Context *ectx = smalloc(sizeof(struct LZ77Context));
|
||||
|
||||
lz77_init(&ectx);
|
||||
ectx.literal = zlib_literal;
|
||||
ectx.match = zlib_match;
|
||||
lz77_init(ectx);
|
||||
ectx->literal = zlib_literal;
|
||||
ectx->match = zlib_match;
|
||||
|
||||
out = smalloc(sizeof(struct Outbuf));
|
||||
out->outbits = out->noutbits = 0;
|
||||
out->firstblock = 1;
|
||||
out->comp_disabled = FALSE;
|
||||
ectx.userdata = out;
|
||||
ectx->userdata = out;
|
||||
|
||||
logevent("Initialised zlib (RFC1950) compression");
|
||||
return ectx;
|
||||
}
|
||||
|
||||
void zlib_compress_cleanup(void *handle)
|
||||
{
|
||||
struct LZ77Context *ectx = (struct LZ77Context *)handle;
|
||||
sfree(ectx->userdata);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -605,9 +610,10 @@ void zlib_compress_init(void)
|
||||
* length adjustment (which is only valid for packets < 65536
|
||||
* bytes, but that seems reasonable enough).
|
||||
*/
|
||||
int zlib_disable_compression(void)
|
||||
int zlib_disable_compression(void *handle)
|
||||
{
|
||||
struct Outbuf *out = (struct Outbuf *) ectx.userdata;
|
||||
struct LZ77Context *ectx = (struct LZ77Context *)handle;
|
||||
struct Outbuf *out = (struct Outbuf *) ectx->userdata;
|
||||
int n;
|
||||
|
||||
out->comp_disabled = TRUE;
|
||||
@ -640,10 +646,11 @@ int zlib_disable_compression(void)
|
||||
return n;
|
||||
}
|
||||
|
||||
int zlib_compress_block(unsigned char *block, int len,
|
||||
int zlib_compress_block(void *handle, unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen)
|
||||
{
|
||||
struct Outbuf *out = (struct Outbuf *) ectx.userdata;
|
||||
struct LZ77Context *ectx = (struct LZ77Context *)handle;
|
||||
struct Outbuf *out = (struct Outbuf *) ectx->userdata;
|
||||
int in_block;
|
||||
|
||||
out->outbuf = NULL;
|
||||
@ -702,7 +709,7 @@ int zlib_compress_block(unsigned char *block, int len,
|
||||
* zlib_literal which will spot out->comp_disabled and
|
||||
* emit in the uncompressed format.
|
||||
*/
|
||||
lz77_compress(&ectx, block, blen, FALSE);
|
||||
lz77_compress(ectx, block, blen, FALSE);
|
||||
|
||||
len -= blen;
|
||||
block += blen;
|
||||
@ -722,7 +729,7 @@ int zlib_compress_block(unsigned char *block, int len,
|
||||
/*
|
||||
* Do the compression.
|
||||
*/
|
||||
lz77_compress(&ectx, block, len, TRUE);
|
||||
lz77_compress(ectx, block, len, TRUE);
|
||||
|
||||
/*
|
||||
* End the block (by transmitting code 256, which is
|
||||
@ -910,7 +917,7 @@ static int zlib_freetable(struct zlib_table **ztab)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct zlib_decompress_ctx {
|
||||
struct zlib_decompress_ctx {
|
||||
struct zlib_table *staticlentable, *staticdisttable;
|
||||
struct zlib_table *currlentable, *currdisttable, *lenlentable;
|
||||
enum {
|
||||
@ -930,23 +937,40 @@ static struct zlib_decompress_ctx {
|
||||
int winpos;
|
||||
unsigned char *outblk;
|
||||
int outlen, outsize;
|
||||
} dctx;
|
||||
};
|
||||
|
||||
void zlib_decompress_init(void)
|
||||
void *zlib_decompress_init(void)
|
||||
{
|
||||
struct zlib_decompress_ctx *dctx =
|
||||
smalloc(sizeof(struct zlib_decompress_ctx));
|
||||
unsigned char lengths[288];
|
||||
|
||||
memset(lengths, 8, 144);
|
||||
memset(lengths + 144, 9, 256 - 144);
|
||||
memset(lengths + 256, 7, 280 - 256);
|
||||
memset(lengths + 280, 8, 288 - 280);
|
||||
dctx.staticlentable = zlib_mktable(lengths, 288);
|
||||
dctx->staticlentable = zlib_mktable(lengths, 288);
|
||||
memset(lengths, 5, 32);
|
||||
dctx.staticdisttable = zlib_mktable(lengths, 32);
|
||||
dctx.state = START; /* even before header */
|
||||
dctx.currlentable = dctx.currdisttable = dctx.lenlentable = NULL;
|
||||
dctx.bits = 0;
|
||||
dctx.nbits = 0;
|
||||
logevent("Initialised zlib (RFC1950) decompression");
|
||||
dctx->staticdisttable = zlib_mktable(lengths, 32);
|
||||
dctx->state = START; /* even before header */
|
||||
dctx->currlentable = dctx->currdisttable = dctx->lenlentable = NULL;
|
||||
dctx->bits = 0;
|
||||
dctx->nbits = 0;
|
||||
|
||||
return dctx;
|
||||
}
|
||||
|
||||
void zlib_decompress_cleanup(void *handle)
|
||||
{
|
||||
struct zlib_decompress_ctx *dctx = (struct zlib_decompress_ctx *)handle;
|
||||
|
||||
if (dctx->currlentable && dctx->currlentable != dctx->staticlentable)
|
||||
zlib_freetable(&dctx->currlentable);
|
||||
if (dctx->currdisttable && dctx->currdisttable != dctx->staticdisttable)
|
||||
zlib_freetable(&dctx->currdisttable);
|
||||
if (dctx->lenlentable)
|
||||
zlib_freetable(&dctx->lenlentable);
|
||||
sfree(dctx);
|
||||
}
|
||||
|
||||
int zlib_huflookup(unsigned long *bitsp, int *nbitsp,
|
||||
@ -971,62 +995,63 @@ int zlib_huflookup(unsigned long *bitsp, int *nbitsp,
|
||||
}
|
||||
}
|
||||
|
||||
static void zlib_emit_char(int c)
|
||||
static void zlib_emit_char(struct zlib_decompress_ctx *dctx, int c)
|
||||
{
|
||||
dctx.window[dctx.winpos] = c;
|
||||
dctx.winpos = (dctx.winpos + 1) & (WINSIZE - 1);
|
||||
if (dctx.outlen >= dctx.outsize) {
|
||||
dctx.outsize = dctx.outlen + 512;
|
||||
dctx.outblk = srealloc(dctx.outblk, dctx.outsize);
|
||||
dctx->window[dctx->winpos] = c;
|
||||
dctx->winpos = (dctx->winpos + 1) & (WINSIZE - 1);
|
||||
if (dctx->outlen >= dctx->outsize) {
|
||||
dctx->outsize = dctx->outlen + 512;
|
||||
dctx->outblk = srealloc(dctx->outblk, dctx->outsize);
|
||||
}
|
||||
dctx.outblk[dctx.outlen++] = c;
|
||||
dctx->outblk[dctx->outlen++] = c;
|
||||
}
|
||||
|
||||
#define EATBITS(n) ( dctx.nbits -= (n), dctx.bits >>= (n) )
|
||||
#define EATBITS(n) ( dctx->nbits -= (n), dctx->bits >>= (n) )
|
||||
|
||||
int zlib_decompress_block(unsigned char *block, int len,
|
||||
int zlib_decompress_block(void *handle, unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen)
|
||||
{
|
||||
struct zlib_decompress_ctx *dctx = (struct zlib_decompress_ctx *)handle;
|
||||
const coderecord *rec;
|
||||
int code, blktype, rep, dist, nlen;
|
||||
static const unsigned char lenlenmap[] = {
|
||||
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
|
||||
};
|
||||
|
||||
dctx.outblk = NULL;
|
||||
dctx.outsize = dctx.outlen = 0;
|
||||
dctx->outblk = NULL;
|
||||
dctx->outsize = dctx->outlen = 0;
|
||||
|
||||
while (len > 0 || dctx.nbits > 0) {
|
||||
while (dctx.nbits < 24 && len > 0) {
|
||||
dctx.bits |= (*block++) << dctx.nbits;
|
||||
dctx.nbits += 8;
|
||||
while (len > 0 || dctx->nbits > 0) {
|
||||
while (dctx->nbits < 24 && len > 0) {
|
||||
dctx->bits |= (*block++) << dctx->nbits;
|
||||
dctx->nbits += 8;
|
||||
len--;
|
||||
}
|
||||
switch (dctx.state) {
|
||||
switch (dctx->state) {
|
||||
case START:
|
||||
/* Expect 16-bit zlib header, which we'll dishonourably ignore. */
|
||||
if (dctx.nbits < 16)
|
||||
if (dctx->nbits < 16)
|
||||
goto finished; /* done all we can */
|
||||
EATBITS(16);
|
||||
dctx.state = OUTSIDEBLK;
|
||||
dctx->state = OUTSIDEBLK;
|
||||
break;
|
||||
case OUTSIDEBLK:
|
||||
/* Expect 3-bit block header. */
|
||||
if (dctx.nbits < 3)
|
||||
if (dctx->nbits < 3)
|
||||
goto finished; /* done all we can */
|
||||
EATBITS(1);
|
||||
blktype = dctx.bits & 3;
|
||||
blktype = dctx->bits & 3;
|
||||
EATBITS(2);
|
||||
if (blktype == 0) {
|
||||
int to_eat = dctx.nbits & 7;
|
||||
dctx.state = UNCOMP_LEN;
|
||||
int to_eat = dctx->nbits & 7;
|
||||
dctx->state = UNCOMP_LEN;
|
||||
EATBITS(to_eat); /* align to byte boundary */
|
||||
} else if (blktype == 1) {
|
||||
dctx.currlentable = dctx.staticlentable;
|
||||
dctx.currdisttable = dctx.staticdisttable;
|
||||
dctx.state = INBLK;
|
||||
dctx->currlentable = dctx->staticlentable;
|
||||
dctx->currdisttable = dctx->staticdisttable;
|
||||
dctx->state = INBLK;
|
||||
} else if (blktype == 2) {
|
||||
dctx.state = TREES_HDR;
|
||||
dctx->state = TREES_HDR;
|
||||
}
|
||||
break;
|
||||
case TREES_HDR:
|
||||
@ -1034,125 +1059,130 @@ int zlib_decompress_block(unsigned char *block, int len,
|
||||
* Dynamic block header. Five bits of HLIT, five of
|
||||
* HDIST, four of HCLEN.
|
||||
*/
|
||||
if (dctx.nbits < 5 + 5 + 4)
|
||||
if (dctx->nbits < 5 + 5 + 4)
|
||||
goto finished; /* done all we can */
|
||||
dctx.hlit = 257 + (dctx.bits & 31);
|
||||
dctx->hlit = 257 + (dctx->bits & 31);
|
||||
EATBITS(5);
|
||||
dctx.hdist = 1 + (dctx.bits & 31);
|
||||
dctx->hdist = 1 + (dctx->bits & 31);
|
||||
EATBITS(5);
|
||||
dctx.hclen = 4 + (dctx.bits & 15);
|
||||
dctx->hclen = 4 + (dctx->bits & 15);
|
||||
EATBITS(4);
|
||||
dctx.lenptr = 0;
|
||||
dctx.state = TREES_LENLEN;
|
||||
memset(dctx.lenlen, 0, sizeof(dctx.lenlen));
|
||||
dctx->lenptr = 0;
|
||||
dctx->state = TREES_LENLEN;
|
||||
memset(dctx->lenlen, 0, sizeof(dctx->lenlen));
|
||||
break;
|
||||
case TREES_LENLEN:
|
||||
if (dctx.nbits < 3)
|
||||
if (dctx->nbits < 3)
|
||||
goto finished;
|
||||
while (dctx.lenptr < dctx.hclen && dctx.nbits >= 3) {
|
||||
dctx.lenlen[lenlenmap[dctx.lenptr++]] =
|
||||
(unsigned char) (dctx.bits & 7);
|
||||
while (dctx->lenptr < dctx->hclen && dctx->nbits >= 3) {
|
||||
dctx->lenlen[lenlenmap[dctx->lenptr++]] =
|
||||
(unsigned char) (dctx->bits & 7);
|
||||
EATBITS(3);
|
||||
}
|
||||
if (dctx.lenptr == dctx.hclen) {
|
||||
dctx.lenlentable = zlib_mktable(dctx.lenlen, 19);
|
||||
dctx.state = TREES_LEN;
|
||||
dctx.lenptr = 0;
|
||||
if (dctx->lenptr == dctx->hclen) {
|
||||
dctx->lenlentable = zlib_mktable(dctx->lenlen, 19);
|
||||
dctx->state = TREES_LEN;
|
||||
dctx->lenptr = 0;
|
||||
}
|
||||
break;
|
||||
case TREES_LEN:
|
||||
if (dctx.lenptr >= dctx.hlit + dctx.hdist) {
|
||||
dctx.currlentable = zlib_mktable(dctx.lengths, dctx.hlit);
|
||||
dctx.currdisttable = zlib_mktable(dctx.lengths + dctx.hlit,
|
||||
dctx.hdist);
|
||||
zlib_freetable(&dctx.lenlentable);
|
||||
dctx.state = INBLK;
|
||||
if (dctx->lenptr >= dctx->hlit + dctx->hdist) {
|
||||
dctx->currlentable = zlib_mktable(dctx->lengths, dctx->hlit);
|
||||
dctx->currdisttable = zlib_mktable(dctx->lengths + dctx->hlit,
|
||||
dctx->hdist);
|
||||
zlib_freetable(&dctx->lenlentable);
|
||||
dctx->lenlentable = NULL;
|
||||
dctx->state = INBLK;
|
||||
break;
|
||||
}
|
||||
code =
|
||||
zlib_huflookup(&dctx.bits, &dctx.nbits, dctx.lenlentable);
|
||||
zlib_huflookup(&dctx->bits, &dctx->nbits, dctx->lenlentable);
|
||||
if (code == -1)
|
||||
goto finished;
|
||||
if (code < 16)
|
||||
dctx.lengths[dctx.lenptr++] = code;
|
||||
dctx->lengths[dctx->lenptr++] = code;
|
||||
else {
|
||||
dctx.lenextrabits = (code == 16 ? 2 : code == 17 ? 3 : 7);
|
||||
dctx.lenaddon = (code == 18 ? 11 : 3);
|
||||
dctx.lenrep = (code == 16 && dctx.lenptr > 0 ?
|
||||
dctx.lengths[dctx.lenptr - 1] : 0);
|
||||
dctx.state = TREES_LENREP;
|
||||
dctx->lenextrabits = (code == 16 ? 2 : code == 17 ? 3 : 7);
|
||||
dctx->lenaddon = (code == 18 ? 11 : 3);
|
||||
dctx->lenrep = (code == 16 && dctx->lenptr > 0 ?
|
||||
dctx->lengths[dctx->lenptr - 1] : 0);
|
||||
dctx->state = TREES_LENREP;
|
||||
}
|
||||
break;
|
||||
case TREES_LENREP:
|
||||
if (dctx.nbits < dctx.lenextrabits)
|
||||
if (dctx->nbits < dctx->lenextrabits)
|
||||
goto finished;
|
||||
rep =
|
||||
dctx.lenaddon +
|
||||
(dctx.bits & ((1 << dctx.lenextrabits) - 1));
|
||||
EATBITS(dctx.lenextrabits);
|
||||
while (rep > 0 && dctx.lenptr < dctx.hlit + dctx.hdist) {
|
||||
dctx.lengths[dctx.lenptr] = dctx.lenrep;
|
||||
dctx.lenptr++;
|
||||
dctx->lenaddon +
|
||||
(dctx->bits & ((1 << dctx->lenextrabits) - 1));
|
||||
EATBITS(dctx->lenextrabits);
|
||||
while (rep > 0 && dctx->lenptr < dctx->hlit + dctx->hdist) {
|
||||
dctx->lengths[dctx->lenptr] = dctx->lenrep;
|
||||
dctx->lenptr++;
|
||||
rep--;
|
||||
}
|
||||
dctx.state = TREES_LEN;
|
||||
dctx->state = TREES_LEN;
|
||||
break;
|
||||
case INBLK:
|
||||
code =
|
||||
zlib_huflookup(&dctx.bits, &dctx.nbits, dctx.currlentable);
|
||||
zlib_huflookup(&dctx->bits, &dctx->nbits, dctx->currlentable);
|
||||
if (code == -1)
|
||||
goto finished;
|
||||
if (code < 256)
|
||||
zlib_emit_char(code);
|
||||
zlib_emit_char(dctx, code);
|
||||
else if (code == 256) {
|
||||
dctx.state = OUTSIDEBLK;
|
||||
if (dctx.currlentable != dctx.staticlentable)
|
||||
zlib_freetable(&dctx.currlentable);
|
||||
if (dctx.currdisttable != dctx.staticdisttable)
|
||||
zlib_freetable(&dctx.currdisttable);
|
||||
dctx->state = OUTSIDEBLK;
|
||||
if (dctx->currlentable != dctx->staticlentable) {
|
||||
zlib_freetable(&dctx->currlentable);
|
||||
dctx->currlentable = NULL;
|
||||
}
|
||||
if (dctx->currdisttable != dctx->staticdisttable) {
|
||||
zlib_freetable(&dctx->currdisttable);
|
||||
dctx->currdisttable = NULL;
|
||||
}
|
||||
} else if (code < 286) { /* static tree can give >285; ignore */
|
||||
dctx.state = GOTLENSYM;
|
||||
dctx.sym = code;
|
||||
dctx->state = GOTLENSYM;
|
||||
dctx->sym = code;
|
||||
}
|
||||
break;
|
||||
case GOTLENSYM:
|
||||
rec = &lencodes[dctx.sym - 257];
|
||||
if (dctx.nbits < rec->extrabits)
|
||||
rec = &lencodes[dctx->sym - 257];
|
||||
if (dctx->nbits < rec->extrabits)
|
||||
goto finished;
|
||||
dctx.len =
|
||||
rec->min + (dctx.bits & ((1 << rec->extrabits) - 1));
|
||||
dctx->len =
|
||||
rec->min + (dctx->bits & ((1 << rec->extrabits) - 1));
|
||||
EATBITS(rec->extrabits);
|
||||
dctx.state = GOTLEN;
|
||||
dctx->state = GOTLEN;
|
||||
break;
|
||||
case GOTLEN:
|
||||
code =
|
||||
zlib_huflookup(&dctx.bits, &dctx.nbits,
|
||||
dctx.currdisttable);
|
||||
zlib_huflookup(&dctx->bits, &dctx->nbits,
|
||||
dctx->currdisttable);
|
||||
if (code == -1)
|
||||
goto finished;
|
||||
dctx.state = GOTDISTSYM;
|
||||
dctx.sym = code;
|
||||
dctx->state = GOTDISTSYM;
|
||||
dctx->sym = code;
|
||||
break;
|
||||
case GOTDISTSYM:
|
||||
rec = &distcodes[dctx.sym];
|
||||
if (dctx.nbits < rec->extrabits)
|
||||
rec = &distcodes[dctx->sym];
|
||||
if (dctx->nbits < rec->extrabits)
|
||||
goto finished;
|
||||
dist = rec->min + (dctx.bits & ((1 << rec->extrabits) - 1));
|
||||
dist = rec->min + (dctx->bits & ((1 << rec->extrabits) - 1));
|
||||
EATBITS(rec->extrabits);
|
||||
dctx.state = INBLK;
|
||||
while (dctx.len--)
|
||||
zlib_emit_char(dctx.window[(dctx.winpos - dist) &
|
||||
(WINSIZE - 1)]);
|
||||
dctx->state = INBLK;
|
||||
while (dctx->len--)
|
||||
zlib_emit_char(dctx, dctx->window[(dctx->winpos - dist) &
|
||||
(WINSIZE - 1)]);
|
||||
break;
|
||||
case UNCOMP_LEN:
|
||||
/*
|
||||
* Uncompressed block. We expect to see a 16-bit LEN.
|
||||
*/
|
||||
if (dctx.nbits < 16)
|
||||
if (dctx->nbits < 16)
|
||||
goto finished;
|
||||
dctx.uncomplen = dctx.bits & 0xFFFF;
|
||||
dctx->uncomplen = dctx->bits & 0xFFFF;
|
||||
EATBITS(16);
|
||||
dctx.state = UNCOMP_NLEN;
|
||||
dctx->state = UNCOMP_NLEN;
|
||||
break;
|
||||
case UNCOMP_NLEN:
|
||||
/*
|
||||
@ -1160,29 +1190,29 @@ int zlib_decompress_block(unsigned char *block, int len,
|
||||
* which should be the one's complement of the previous
|
||||
* LEN.
|
||||
*/
|
||||
if (dctx.nbits < 16)
|
||||
if (dctx->nbits < 16)
|
||||
goto finished;
|
||||
nlen = dctx.bits & 0xFFFF;
|
||||
nlen = dctx->bits & 0xFFFF;
|
||||
EATBITS(16);
|
||||
if (dctx.uncomplen == 0)
|
||||
dctx.state = OUTSIDEBLK; /* block is empty */
|
||||
if (dctx->uncomplen == 0)
|
||||
dctx->state = OUTSIDEBLK; /* block is empty */
|
||||
else
|
||||
dctx.state = UNCOMP_DATA;
|
||||
dctx->state = UNCOMP_DATA;
|
||||
break;
|
||||
case UNCOMP_DATA:
|
||||
if (dctx.nbits < 8)
|
||||
if (dctx->nbits < 8)
|
||||
goto finished;
|
||||
zlib_emit_char(dctx.bits & 0xFF);
|
||||
zlib_emit_char(dctx, dctx->bits & 0xFF);
|
||||
EATBITS(8);
|
||||
if (--dctx.uncomplen == 0)
|
||||
dctx.state = OUTSIDEBLK; /* end of uncompressed block */
|
||||
if (--dctx->uncomplen == 0)
|
||||
dctx->state = OUTSIDEBLK; /* end of uncompressed block */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
finished:
|
||||
*outblock = dctx.outblk;
|
||||
*outlen = dctx.outlen;
|
||||
*outblock = dctx->outblk;
|
||||
*outlen = dctx->outlen;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1190,8 +1220,11 @@ int zlib_decompress_block(unsigned char *block, int len,
|
||||
const struct ssh_compress ssh_zlib = {
|
||||
"zlib",
|
||||
zlib_compress_init,
|
||||
zlib_compress_cleanup,
|
||||
zlib_compress_block,
|
||||
zlib_decompress_init,
|
||||
zlib_decompress_cleanup,
|
||||
zlib_decompress_block,
|
||||
zlib_disable_compression
|
||||
zlib_disable_compression,
|
||||
"zlib (RFC1950)"
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user