mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-26 09:42:25 +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
|
&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)
|
unsigned char **outblock, int *outlen)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int ssh_comp_none_disable(void)
|
static int ssh_comp_none_disable(void *handle)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const static struct ssh_compress ssh_comp_none = {
|
const static struct ssh_compress ssh_comp_none = {
|
||||||
"none",
|
"none",
|
||||||
ssh_comp_none_init, ssh_comp_none_block,
|
ssh_comp_none_init, ssh_comp_none_cleanup, ssh_comp_none_block,
|
||||||
ssh_comp_none_init, ssh_comp_none_block,
|
ssh_comp_none_init, ssh_comp_none_cleanup, ssh_comp_none_block,
|
||||||
ssh_comp_none_disable
|
ssh_comp_none_disable, NULL
|
||||||
};
|
};
|
||||||
extern const struct ssh_compress ssh_zlib;
|
extern const struct ssh_compress ssh_zlib;
|
||||||
const static struct ssh_compress *compressions[] = {
|
const static struct ssh_compress *compressions[] = {
|
||||||
@ -566,6 +570,7 @@ struct ssh_tag {
|
|||||||
const struct ssh_mac *csmac, *scmac;
|
const struct ssh_mac *csmac, *scmac;
|
||||||
void *cs_mac_ctx, *sc_mac_ctx;
|
void *cs_mac_ctx, *sc_mac_ctx;
|
||||||
const struct ssh_compress *cscomp, *sccomp;
|
const struct ssh_compress *cscomp, *sccomp;
|
||||||
|
void *cs_comp_ctx, *sc_comp_ctx;
|
||||||
const struct ssh_kex *kex;
|
const struct ssh_kex *kex;
|
||||||
const struct ssh_signkey *hostkey;
|
const struct ssh_signkey *hostkey;
|
||||||
unsigned char v2_session_id[20];
|
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) {
|
if (ssh->v1_compressing) {
|
||||||
unsigned char *decompblk;
|
unsigned char *decompblk;
|
||||||
int decomplen;
|
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);
|
&decompblk, &decomplen);
|
||||||
|
|
||||||
if (ssh->pktin.maxlen < st->pad + 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;
|
unsigned char *newpayload;
|
||||||
int newlen;
|
int newlen;
|
||||||
if (ssh->sccomp &&
|
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)) {
|
&newpayload, &newlen)) {
|
||||||
if (ssh->pktin.maxlen < newlen + 5) {
|
if (ssh->pktin.maxlen < newlen + 5) {
|
||||||
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) {
|
if (ssh->v1_compressing) {
|
||||||
unsigned char *compblk;
|
unsigned char *compblk;
|
||||||
int complen;
|
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);
|
&compblk, &complen);
|
||||||
ssh1_pktout_size(ssh, complen - 1);
|
ssh1_pktout_size(ssh, complen - 1);
|
||||||
memcpy(ssh->pktout.body - 1, compblk, complen);
|
memcpy(ssh->pktout.body - 1, compblk, complen);
|
||||||
@ -1457,7 +1465,8 @@ static int ssh2_pkt_construct(Ssh ssh)
|
|||||||
unsigned char *newpayload;
|
unsigned char *newpayload;
|
||||||
int newlen;
|
int newlen;
|
||||||
if (ssh->cscomp &&
|
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)) {
|
&newpayload, &newlen)) {
|
||||||
ssh->pktout.length = 5;
|
ssh->pktout.length = 5;
|
||||||
ssh2_pkt_adddata(ssh, newpayload, newlen);
|
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");
|
logevent("Started compression");
|
||||||
ssh->v1_compressing = TRUE;
|
ssh->v1_compressing = TRUE;
|
||||||
zlib_compress_init();
|
ssh->cs_comp_ctx = zlib_compress_init();
|
||||||
zlib_decompress_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->scmac = s->scmac_tobe;
|
||||||
ssh->sc_mac_ctx = ssh->scmac->make_context();
|
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->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->sccomp = s->sccomp_tobe;
|
||||||
ssh->cscomp->compress_init();
|
ssh->sc_comp_ctx = ssh->sccomp->decompress_init();
|
||||||
ssh->sccomp->decompress_init();
|
|
||||||
/*
|
/*
|
||||||
* Set IVs after keys. Here we use the exchange hash from the
|
* Set IVs after keys. Here we use the exchange hash from the
|
||||||
* _first_ key exchange.
|
* _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",
|
sprintf(buf, "Initialised %.200s server->client encryption",
|
||||||
ssh->sccipher->text_name);
|
ssh->sccipher->text_name);
|
||||||
logevent(buf);
|
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
|
* bytes we should adjust our string length
|
||||||
* by.
|
* by.
|
||||||
*/
|
*/
|
||||||
stringlen -= ssh->cscomp->disable_compression();
|
stringlen -=
|
||||||
|
ssh->cscomp->disable_compression(ssh->cs_comp_ctx);
|
||||||
}
|
}
|
||||||
ssh2_pkt_init(ssh, SSH2_MSG_IGNORE);
|
ssh2_pkt_init(ssh, SSH2_MSG_IGNORE);
|
||||||
ssh2_pkt_addstring_start(ssh);
|
ssh2_pkt_addstring_start(ssh);
|
||||||
@ -5817,7 +5845,9 @@ static char *ssh_init(void *frontend_handle, void **backend_handle,
|
|||||||
ssh->scmac = NULL;
|
ssh->scmac = NULL;
|
||||||
ssh->sc_mac_ctx = NULL;
|
ssh->sc_mac_ctx = NULL;
|
||||||
ssh->cscomp = NULL;
|
ssh->cscomp = NULL;
|
||||||
|
ssh->cs_comp_ctx = NULL;
|
||||||
ssh->sccomp = NULL;
|
ssh->sccomp = NULL;
|
||||||
|
ssh->sc_comp_ctx = NULL;
|
||||||
ssh->kex = NULL;
|
ssh->kex = NULL;
|
||||||
ssh->hostkey = NULL;
|
ssh->hostkey = NULL;
|
||||||
ssh->exitcode = -1;
|
ssh->exitcode = -1;
|
||||||
|
23
ssh.h
23
ssh.h
@ -195,13 +195,16 @@ struct ssh_signkey {
|
|||||||
|
|
||||||
struct ssh_compress {
|
struct ssh_compress {
|
||||||
char *name;
|
char *name;
|
||||||
void (*compress_init) (void);
|
void *(*compress_init) (void);
|
||||||
int (*compress) (unsigned char *block, int len,
|
void (*compress_cleanup) (void *);
|
||||||
|
int (*compress) (void *, unsigned char *block, int len,
|
||||||
unsigned char **outblock, int *outlen);
|
unsigned char **outblock, int *outlen);
|
||||||
void (*decompress_init) (void);
|
void *(*decompress_init) (void);
|
||||||
int (*decompress) (unsigned char *block, int len,
|
void (*decompress_cleanup) (void *);
|
||||||
|
int (*decompress) (void *, unsigned char *block, int len,
|
||||||
unsigned char **outblock, int *outlen);
|
unsigned char **outblock, int *outlen);
|
||||||
int (*disable_compression) (void);
|
int (*disable_compression) (void *);
|
||||||
|
char *text_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ssh2_userkey {
|
struct ssh2_userkey {
|
||||||
@ -359,11 +362,13 @@ Bignum primegen(int bits, int modulus, int residue, Bignum factor,
|
|||||||
/*
|
/*
|
||||||
* zlib compression.
|
* zlib compression.
|
||||||
*/
|
*/
|
||||||
void zlib_compress_init(void);
|
void *zlib_compress_init(void);
|
||||||
void zlib_decompress_init(void);
|
void zlib_compress_cleanup(void *);
|
||||||
int zlib_compress_block(unsigned char *block, int len,
|
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);
|
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);
|
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.
|
* having to transmit the trees.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static struct LZ77Context ectx;
|
|
||||||
|
|
||||||
struct Outbuf {
|
struct Outbuf {
|
||||||
unsigned char *outbuf;
|
unsigned char *outbuf;
|
||||||
int outlen, outsize;
|
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 Outbuf *out;
|
||||||
|
struct LZ77Context *ectx = smalloc(sizeof(struct LZ77Context));
|
||||||
|
|
||||||
lz77_init(&ectx);
|
lz77_init(ectx);
|
||||||
ectx.literal = zlib_literal;
|
ectx->literal = zlib_literal;
|
||||||
ectx.match = zlib_match;
|
ectx->match = zlib_match;
|
||||||
|
|
||||||
out = smalloc(sizeof(struct Outbuf));
|
out = smalloc(sizeof(struct Outbuf));
|
||||||
out->outbits = out->noutbits = 0;
|
out->outbits = out->noutbits = 0;
|
||||||
out->firstblock = 1;
|
out->firstblock = 1;
|
||||||
out->comp_disabled = FALSE;
|
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
|
* length adjustment (which is only valid for packets < 65536
|
||||||
* bytes, but that seems reasonable enough).
|
* 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;
|
int n;
|
||||||
|
|
||||||
out->comp_disabled = TRUE;
|
out->comp_disabled = TRUE;
|
||||||
@ -640,10 +646,11 @@ int zlib_disable_compression(void)
|
|||||||
return n;
|
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)
|
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;
|
int in_block;
|
||||||
|
|
||||||
out->outbuf = NULL;
|
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
|
* zlib_literal which will spot out->comp_disabled and
|
||||||
* emit in the uncompressed format.
|
* emit in the uncompressed format.
|
||||||
*/
|
*/
|
||||||
lz77_compress(&ectx, block, blen, FALSE);
|
lz77_compress(ectx, block, blen, FALSE);
|
||||||
|
|
||||||
len -= blen;
|
len -= blen;
|
||||||
block += blen;
|
block += blen;
|
||||||
@ -722,7 +729,7 @@ int zlib_compress_block(unsigned char *block, int len,
|
|||||||
/*
|
/*
|
||||||
* Do the compression.
|
* Do the compression.
|
||||||
*/
|
*/
|
||||||
lz77_compress(&ectx, block, len, TRUE);
|
lz77_compress(ectx, block, len, TRUE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* End the block (by transmitting code 256, which is
|
* End the block (by transmitting code 256, which is
|
||||||
@ -910,7 +917,7 @@ static int zlib_freetable(struct zlib_table **ztab)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct zlib_decompress_ctx {
|
struct zlib_decompress_ctx {
|
||||||
struct zlib_table *staticlentable, *staticdisttable;
|
struct zlib_table *staticlentable, *staticdisttable;
|
||||||
struct zlib_table *currlentable, *currdisttable, *lenlentable;
|
struct zlib_table *currlentable, *currdisttable, *lenlentable;
|
||||||
enum {
|
enum {
|
||||||
@ -930,23 +937,40 @@ static struct zlib_decompress_ctx {
|
|||||||
int winpos;
|
int winpos;
|
||||||
unsigned char *outblk;
|
unsigned char *outblk;
|
||||||
int outlen, outsize;
|
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];
|
unsigned char lengths[288];
|
||||||
|
|
||||||
memset(lengths, 8, 144);
|
memset(lengths, 8, 144);
|
||||||
memset(lengths + 144, 9, 256 - 144);
|
memset(lengths + 144, 9, 256 - 144);
|
||||||
memset(lengths + 256, 7, 280 - 256);
|
memset(lengths + 256, 7, 280 - 256);
|
||||||
memset(lengths + 280, 8, 288 - 280);
|
memset(lengths + 280, 8, 288 - 280);
|
||||||
dctx.staticlentable = zlib_mktable(lengths, 288);
|
dctx->staticlentable = zlib_mktable(lengths, 288);
|
||||||
memset(lengths, 5, 32);
|
memset(lengths, 5, 32);
|
||||||
dctx.staticdisttable = zlib_mktable(lengths, 32);
|
dctx->staticdisttable = zlib_mktable(lengths, 32);
|
||||||
dctx.state = START; /* even before header */
|
dctx->state = START; /* even before header */
|
||||||
dctx.currlentable = dctx.currdisttable = dctx.lenlentable = NULL;
|
dctx->currlentable = dctx->currdisttable = dctx->lenlentable = NULL;
|
||||||
dctx.bits = 0;
|
dctx->bits = 0;
|
||||||
dctx.nbits = 0;
|
dctx->nbits = 0;
|
||||||
logevent("Initialised zlib (RFC1950) decompression");
|
|
||||||
|
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,
|
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->window[dctx->winpos] = c;
|
||||||
dctx.winpos = (dctx.winpos + 1) & (WINSIZE - 1);
|
dctx->winpos = (dctx->winpos + 1) & (WINSIZE - 1);
|
||||||
if (dctx.outlen >= dctx.outsize) {
|
if (dctx->outlen >= dctx->outsize) {
|
||||||
dctx.outsize = dctx.outlen + 512;
|
dctx->outsize = dctx->outlen + 512;
|
||||||
dctx.outblk = srealloc(dctx.outblk, dctx.outsize);
|
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)
|
unsigned char **outblock, int *outlen)
|
||||||
{
|
{
|
||||||
|
struct zlib_decompress_ctx *dctx = (struct zlib_decompress_ctx *)handle;
|
||||||
const coderecord *rec;
|
const coderecord *rec;
|
||||||
int code, blktype, rep, dist, nlen;
|
int code, blktype, rep, dist, nlen;
|
||||||
static const unsigned char lenlenmap[] = {
|
static const unsigned char lenlenmap[] = {
|
||||||
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
|
||||||
};
|
};
|
||||||
|
|
||||||
dctx.outblk = NULL;
|
dctx->outblk = NULL;
|
||||||
dctx.outsize = dctx.outlen = 0;
|
dctx->outsize = dctx->outlen = 0;
|
||||||
|
|
||||||
while (len > 0 || dctx.nbits > 0) {
|
while (len > 0 || dctx->nbits > 0) {
|
||||||
while (dctx.nbits < 24 && len > 0) {
|
while (dctx->nbits < 24 && len > 0) {
|
||||||
dctx.bits |= (*block++) << dctx.nbits;
|
dctx->bits |= (*block++) << dctx->nbits;
|
||||||
dctx.nbits += 8;
|
dctx->nbits += 8;
|
||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
switch (dctx.state) {
|
switch (dctx->state) {
|
||||||
case START:
|
case START:
|
||||||
/* Expect 16-bit zlib header, which we'll dishonourably ignore. */
|
/* Expect 16-bit zlib header, which we'll dishonourably ignore. */
|
||||||
if (dctx.nbits < 16)
|
if (dctx->nbits < 16)
|
||||||
goto finished; /* done all we can */
|
goto finished; /* done all we can */
|
||||||
EATBITS(16);
|
EATBITS(16);
|
||||||
dctx.state = OUTSIDEBLK;
|
dctx->state = OUTSIDEBLK;
|
||||||
break;
|
break;
|
||||||
case OUTSIDEBLK:
|
case OUTSIDEBLK:
|
||||||
/* Expect 3-bit block header. */
|
/* Expect 3-bit block header. */
|
||||||
if (dctx.nbits < 3)
|
if (dctx->nbits < 3)
|
||||||
goto finished; /* done all we can */
|
goto finished; /* done all we can */
|
||||||
EATBITS(1);
|
EATBITS(1);
|
||||||
blktype = dctx.bits & 3;
|
blktype = dctx->bits & 3;
|
||||||
EATBITS(2);
|
EATBITS(2);
|
||||||
if (blktype == 0) {
|
if (blktype == 0) {
|
||||||
int to_eat = dctx.nbits & 7;
|
int to_eat = dctx->nbits & 7;
|
||||||
dctx.state = UNCOMP_LEN;
|
dctx->state = UNCOMP_LEN;
|
||||||
EATBITS(to_eat); /* align to byte boundary */
|
EATBITS(to_eat); /* align to byte boundary */
|
||||||
} else if (blktype == 1) {
|
} else if (blktype == 1) {
|
||||||
dctx.currlentable = dctx.staticlentable;
|
dctx->currlentable = dctx->staticlentable;
|
||||||
dctx.currdisttable = dctx.staticdisttable;
|
dctx->currdisttable = dctx->staticdisttable;
|
||||||
dctx.state = INBLK;
|
dctx->state = INBLK;
|
||||||
} else if (blktype == 2) {
|
} else if (blktype == 2) {
|
||||||
dctx.state = TREES_HDR;
|
dctx->state = TREES_HDR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TREES_HDR:
|
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
|
* Dynamic block header. Five bits of HLIT, five of
|
||||||
* HDIST, four of HCLEN.
|
* HDIST, four of HCLEN.
|
||||||
*/
|
*/
|
||||||
if (dctx.nbits < 5 + 5 + 4)
|
if (dctx->nbits < 5 + 5 + 4)
|
||||||
goto finished; /* done all we can */
|
goto finished; /* done all we can */
|
||||||
dctx.hlit = 257 + (dctx.bits & 31);
|
dctx->hlit = 257 + (dctx->bits & 31);
|
||||||
EATBITS(5);
|
EATBITS(5);
|
||||||
dctx.hdist = 1 + (dctx.bits & 31);
|
dctx->hdist = 1 + (dctx->bits & 31);
|
||||||
EATBITS(5);
|
EATBITS(5);
|
||||||
dctx.hclen = 4 + (dctx.bits & 15);
|
dctx->hclen = 4 + (dctx->bits & 15);
|
||||||
EATBITS(4);
|
EATBITS(4);
|
||||||
dctx.lenptr = 0;
|
dctx->lenptr = 0;
|
||||||
dctx.state = TREES_LENLEN;
|
dctx->state = TREES_LENLEN;
|
||||||
memset(dctx.lenlen, 0, sizeof(dctx.lenlen));
|
memset(dctx->lenlen, 0, sizeof(dctx->lenlen));
|
||||||
break;
|
break;
|
||||||
case TREES_LENLEN:
|
case TREES_LENLEN:
|
||||||
if (dctx.nbits < 3)
|
if (dctx->nbits < 3)
|
||||||
goto finished;
|
goto finished;
|
||||||
while (dctx.lenptr < dctx.hclen && dctx.nbits >= 3) {
|
while (dctx->lenptr < dctx->hclen && dctx->nbits >= 3) {
|
||||||
dctx.lenlen[lenlenmap[dctx.lenptr++]] =
|
dctx->lenlen[lenlenmap[dctx->lenptr++]] =
|
||||||
(unsigned char) (dctx.bits & 7);
|
(unsigned char) (dctx->bits & 7);
|
||||||
EATBITS(3);
|
EATBITS(3);
|
||||||
}
|
}
|
||||||
if (dctx.lenptr == dctx.hclen) {
|
if (dctx->lenptr == dctx->hclen) {
|
||||||
dctx.lenlentable = zlib_mktable(dctx.lenlen, 19);
|
dctx->lenlentable = zlib_mktable(dctx->lenlen, 19);
|
||||||
dctx.state = TREES_LEN;
|
dctx->state = TREES_LEN;
|
||||||
dctx.lenptr = 0;
|
dctx->lenptr = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TREES_LEN:
|
case TREES_LEN:
|
||||||
if (dctx.lenptr >= dctx.hlit + dctx.hdist) {
|
if (dctx->lenptr >= dctx->hlit + dctx->hdist) {
|
||||||
dctx.currlentable = zlib_mktable(dctx.lengths, dctx.hlit);
|
dctx->currlentable = zlib_mktable(dctx->lengths, dctx->hlit);
|
||||||
dctx.currdisttable = zlib_mktable(dctx.lengths + dctx.hlit,
|
dctx->currdisttable = zlib_mktable(dctx->lengths + dctx->hlit,
|
||||||
dctx.hdist);
|
dctx->hdist);
|
||||||
zlib_freetable(&dctx.lenlentable);
|
zlib_freetable(&dctx->lenlentable);
|
||||||
dctx.state = INBLK;
|
dctx->lenlentable = NULL;
|
||||||
|
dctx->state = INBLK;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
code =
|
code =
|
||||||
zlib_huflookup(&dctx.bits, &dctx.nbits, dctx.lenlentable);
|
zlib_huflookup(&dctx->bits, &dctx->nbits, dctx->lenlentable);
|
||||||
if (code == -1)
|
if (code == -1)
|
||||||
goto finished;
|
goto finished;
|
||||||
if (code < 16)
|
if (code < 16)
|
||||||
dctx.lengths[dctx.lenptr++] = code;
|
dctx->lengths[dctx->lenptr++] = code;
|
||||||
else {
|
else {
|
||||||
dctx.lenextrabits = (code == 16 ? 2 : code == 17 ? 3 : 7);
|
dctx->lenextrabits = (code == 16 ? 2 : code == 17 ? 3 : 7);
|
||||||
dctx.lenaddon = (code == 18 ? 11 : 3);
|
dctx->lenaddon = (code == 18 ? 11 : 3);
|
||||||
dctx.lenrep = (code == 16 && dctx.lenptr > 0 ?
|
dctx->lenrep = (code == 16 && dctx->lenptr > 0 ?
|
||||||
dctx.lengths[dctx.lenptr - 1] : 0);
|
dctx->lengths[dctx->lenptr - 1] : 0);
|
||||||
dctx.state = TREES_LENREP;
|
dctx->state = TREES_LENREP;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TREES_LENREP:
|
case TREES_LENREP:
|
||||||
if (dctx.nbits < dctx.lenextrabits)
|
if (dctx->nbits < dctx->lenextrabits)
|
||||||
goto finished;
|
goto finished;
|
||||||
rep =
|
rep =
|
||||||
dctx.lenaddon +
|
dctx->lenaddon +
|
||||||
(dctx.bits & ((1 << dctx.lenextrabits) - 1));
|
(dctx->bits & ((1 << dctx->lenextrabits) - 1));
|
||||||
EATBITS(dctx.lenextrabits);
|
EATBITS(dctx->lenextrabits);
|
||||||
while (rep > 0 && dctx.lenptr < dctx.hlit + dctx.hdist) {
|
while (rep > 0 && dctx->lenptr < dctx->hlit + dctx->hdist) {
|
||||||
dctx.lengths[dctx.lenptr] = dctx.lenrep;
|
dctx->lengths[dctx->lenptr] = dctx->lenrep;
|
||||||
dctx.lenptr++;
|
dctx->lenptr++;
|
||||||
rep--;
|
rep--;
|
||||||
}
|
}
|
||||||
dctx.state = TREES_LEN;
|
dctx->state = TREES_LEN;
|
||||||
break;
|
break;
|
||||||
case INBLK:
|
case INBLK:
|
||||||
code =
|
code =
|
||||||
zlib_huflookup(&dctx.bits, &dctx.nbits, dctx.currlentable);
|
zlib_huflookup(&dctx->bits, &dctx->nbits, dctx->currlentable);
|
||||||
if (code == -1)
|
if (code == -1)
|
||||||
goto finished;
|
goto finished;
|
||||||
if (code < 256)
|
if (code < 256)
|
||||||
zlib_emit_char(code);
|
zlib_emit_char(dctx, code);
|
||||||
else if (code == 256) {
|
else if (code == 256) {
|
||||||
dctx.state = OUTSIDEBLK;
|
dctx->state = OUTSIDEBLK;
|
||||||
if (dctx.currlentable != dctx.staticlentable)
|
if (dctx->currlentable != dctx->staticlentable) {
|
||||||
zlib_freetable(&dctx.currlentable);
|
zlib_freetable(&dctx->currlentable);
|
||||||
if (dctx.currdisttable != dctx.staticdisttable)
|
dctx->currlentable = NULL;
|
||||||
zlib_freetable(&dctx.currdisttable);
|
}
|
||||||
|
if (dctx->currdisttable != dctx->staticdisttable) {
|
||||||
|
zlib_freetable(&dctx->currdisttable);
|
||||||
|
dctx->currdisttable = NULL;
|
||||||
|
}
|
||||||
} else if (code < 286) { /* static tree can give >285; ignore */
|
} else if (code < 286) { /* static tree can give >285; ignore */
|
||||||
dctx.state = GOTLENSYM;
|
dctx->state = GOTLENSYM;
|
||||||
dctx.sym = code;
|
dctx->sym = code;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GOTLENSYM:
|
case GOTLENSYM:
|
||||||
rec = &lencodes[dctx.sym - 257];
|
rec = &lencodes[dctx->sym - 257];
|
||||||
if (dctx.nbits < rec->extrabits)
|
if (dctx->nbits < rec->extrabits)
|
||||||
goto finished;
|
goto finished;
|
||||||
dctx.len =
|
dctx->len =
|
||||||
rec->min + (dctx.bits & ((1 << rec->extrabits) - 1));
|
rec->min + (dctx->bits & ((1 << rec->extrabits) - 1));
|
||||||
EATBITS(rec->extrabits);
|
EATBITS(rec->extrabits);
|
||||||
dctx.state = GOTLEN;
|
dctx->state = GOTLEN;
|
||||||
break;
|
break;
|
||||||
case GOTLEN:
|
case GOTLEN:
|
||||||
code =
|
code =
|
||||||
zlib_huflookup(&dctx.bits, &dctx.nbits,
|
zlib_huflookup(&dctx->bits, &dctx->nbits,
|
||||||
dctx.currdisttable);
|
dctx->currdisttable);
|
||||||
if (code == -1)
|
if (code == -1)
|
||||||
goto finished;
|
goto finished;
|
||||||
dctx.state = GOTDISTSYM;
|
dctx->state = GOTDISTSYM;
|
||||||
dctx.sym = code;
|
dctx->sym = code;
|
||||||
break;
|
break;
|
||||||
case GOTDISTSYM:
|
case GOTDISTSYM:
|
||||||
rec = &distcodes[dctx.sym];
|
rec = &distcodes[dctx->sym];
|
||||||
if (dctx.nbits < rec->extrabits)
|
if (dctx->nbits < rec->extrabits)
|
||||||
goto finished;
|
goto finished;
|
||||||
dist = rec->min + (dctx.bits & ((1 << rec->extrabits) - 1));
|
dist = rec->min + (dctx->bits & ((1 << rec->extrabits) - 1));
|
||||||
EATBITS(rec->extrabits);
|
EATBITS(rec->extrabits);
|
||||||
dctx.state = INBLK;
|
dctx->state = INBLK;
|
||||||
while (dctx.len--)
|
while (dctx->len--)
|
||||||
zlib_emit_char(dctx.window[(dctx.winpos - dist) &
|
zlib_emit_char(dctx, dctx->window[(dctx->winpos - dist) &
|
||||||
(WINSIZE - 1)]);
|
(WINSIZE - 1)]);
|
||||||
break;
|
break;
|
||||||
case UNCOMP_LEN:
|
case UNCOMP_LEN:
|
||||||
/*
|
/*
|
||||||
* Uncompressed block. We expect to see a 16-bit LEN.
|
* Uncompressed block. We expect to see a 16-bit LEN.
|
||||||
*/
|
*/
|
||||||
if (dctx.nbits < 16)
|
if (dctx->nbits < 16)
|
||||||
goto finished;
|
goto finished;
|
||||||
dctx.uncomplen = dctx.bits & 0xFFFF;
|
dctx->uncomplen = dctx->bits & 0xFFFF;
|
||||||
EATBITS(16);
|
EATBITS(16);
|
||||||
dctx.state = UNCOMP_NLEN;
|
dctx->state = UNCOMP_NLEN;
|
||||||
break;
|
break;
|
||||||
case UNCOMP_NLEN:
|
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
|
* which should be the one's complement of the previous
|
||||||
* LEN.
|
* LEN.
|
||||||
*/
|
*/
|
||||||
if (dctx.nbits < 16)
|
if (dctx->nbits < 16)
|
||||||
goto finished;
|
goto finished;
|
||||||
nlen = dctx.bits & 0xFFFF;
|
nlen = dctx->bits & 0xFFFF;
|
||||||
EATBITS(16);
|
EATBITS(16);
|
||||||
if (dctx.uncomplen == 0)
|
if (dctx->uncomplen == 0)
|
||||||
dctx.state = OUTSIDEBLK; /* block is empty */
|
dctx->state = OUTSIDEBLK; /* block is empty */
|
||||||
else
|
else
|
||||||
dctx.state = UNCOMP_DATA;
|
dctx->state = UNCOMP_DATA;
|
||||||
break;
|
break;
|
||||||
case UNCOMP_DATA:
|
case UNCOMP_DATA:
|
||||||
if (dctx.nbits < 8)
|
if (dctx->nbits < 8)
|
||||||
goto finished;
|
goto finished;
|
||||||
zlib_emit_char(dctx.bits & 0xFF);
|
zlib_emit_char(dctx, dctx->bits & 0xFF);
|
||||||
EATBITS(8);
|
EATBITS(8);
|
||||||
if (--dctx.uncomplen == 0)
|
if (--dctx->uncomplen == 0)
|
||||||
dctx.state = OUTSIDEBLK; /* end of uncompressed block */
|
dctx->state = OUTSIDEBLK; /* end of uncompressed block */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
finished:
|
finished:
|
||||||
*outblock = dctx.outblk;
|
*outblock = dctx->outblk;
|
||||||
*outlen = dctx.outlen;
|
*outlen = dctx->outlen;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1190,8 +1220,11 @@ int zlib_decompress_block(unsigned char *block, int len,
|
|||||||
const struct ssh_compress ssh_zlib = {
|
const struct ssh_compress ssh_zlib = {
|
||||||
"zlib",
|
"zlib",
|
||||||
zlib_compress_init,
|
zlib_compress_init,
|
||||||
|
zlib_compress_cleanup,
|
||||||
zlib_compress_block,
|
zlib_compress_block,
|
||||||
zlib_decompress_init,
|
zlib_decompress_init,
|
||||||
|
zlib_decompress_cleanup,
|
||||||
zlib_decompress_block,
|
zlib_decompress_block,
|
||||||
zlib_disable_compression
|
zlib_disable_compression,
|
||||||
|
"zlib (RFC1950)"
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user