From: Simon Tatham Date: Thu, 26 Jun 2003 13:41:30 +0000 (+0000) Subject: Fix a segfault (non-security-critical - null dereference for X-Git-Tag: r8855-g4f798d~1354 X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=commitdiff_plain;h=e91620ae7f1b59fc7a8d825c871e9c2a519c4f79;p=PuTTY_svn.git 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: http://svn.tartarus.org/sgt/putty@3306 cda61777-01e9-0310-a592-d414129be87e --- 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 = {