From 36b8d9bb9274b5ca088063a83d255121691a579f Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 26 Jun 2003 13:41:30 +0000 Subject: [PATCH] Fix a segfault (non-security-critical - null dereference for reading) in the zlib code when fed certain kinds of invalid data. As a result, ssh.c now needs to be prepared for zlib_decompress_block to return failure. git-svn-id: svn://svn.tartarus.org/sgt/putty@3306 cda61777-01e9-0310-a592-d414129be87e --- ssh.c | 9 ++++++--- sshzlib.c | 23 ++++++++++++++++++++++- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/ssh.c b/ssh.c index 16ceb013..f06b2df2 100644 --- a/ssh.c +++ b/ssh.c @@ -868,9 +868,12 @@ static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen) if (ssh->v1_compressing) { unsigned char *decompblk; int decomplen; - zlib_decompress_block(ssh->sc_comp_ctx, - ssh->pktin.body - 1, ssh->pktin.length + 1, - &decompblk, &decomplen); + if (!zlib_decompress_block(ssh->sc_comp_ctx, + ssh->pktin.body - 1, ssh->pktin.length + 1, + &decompblk, &decomplen)) { + bombout(("Zlib decompression encountered invalid data")); + crStop(0); + } if (ssh->pktin.maxlen < st->pad + decomplen) { ssh->pktin.maxlen = st->pad + decomplen; diff --git a/sshzlib.c b/sshzlib.c index a98d96c6..91f5537f 100644 --- a/sshzlib.c +++ b/sshzlib.c @@ -992,6 +992,16 @@ static int zlib_huflookup(unsigned long *bitsp, int *nbitsp, *nbitsp = nbits; return ent->code; } + + if (!tab) { + /* + * There was a missing entry in the table, presumably + * due to an invalid Huffman table description, and the + * subsequent data has attempted to use the missing + * entry. Return a decoding failure. + */ + return -2; + } } } @@ -1099,6 +1109,8 @@ int zlib_decompress_block(void *handle, unsigned char *block, int len, zlib_huflookup(&dctx->bits, &dctx->nbits, dctx->lenlentable); if (code == -1) goto finished; + if (code == -2) + goto decode_error; if (code < 16) dctx->lengths[dctx->lenptr++] = code; else { @@ -1128,6 +1140,8 @@ int zlib_decompress_block(void *handle, unsigned char *block, int len, zlib_huflookup(&dctx->bits, &dctx->nbits, dctx->currlentable); if (code == -1) goto finished; + if (code == -2) + goto decode_error; if (code < 256) zlib_emit_char(dctx, code); else if (code == 256) { @@ -1160,6 +1174,8 @@ int zlib_decompress_block(void *handle, unsigned char *block, int len, dctx->currdisttable); if (code == -1) goto finished; + if (code == -2) + goto decode_error; dctx->state = GOTDISTSYM; dctx->sym = code; break; @@ -1213,8 +1229,13 @@ int zlib_decompress_block(void *handle, unsigned char *block, int len, finished: *outblock = dctx->outblk; *outlen = dctx->outlen; - return 1; + + decode_error: + sfree(dctx->outblk); + *outblock = dctx->outblk = NULL; + *outlen = 0; + return 0; } const struct ssh_compress ssh_zlib = { -- 2.11.0