Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Reject negative output length in SpanInfo
  • Loading branch information
kyz committed Aug 13, 2017
1 parent ca6e065 commit 6139a0b
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 5 deletions.
13 changes: 13 additions & 0 deletions libmspack/ChangeLog
@@ -1,3 +1,16 @@
2017-08-13 Stuart Caie <kyzer@cabextract.org.uk>

* read_spaninfo(): a CHM file can have no ResetTable and have a
negative length in SpanInfo, which then feeds a negative output length
to lzxd_init(), which then sets frame_size to a value of your choosing,
the lower 32 bits of output length, larger than LZX_FRAME_SIZE. If the
first LZX block is uncompressed, this writes data beyond the end of the
window. This issue was raised by ClamAV as CVE-2017-6419. Thanks to
Sebastian Andrzej Siewior for finding this by chance!

* lzxd_init(), lzxd_set_output_length(), mszipd_init(): due to the issue
mentioned above, these functions now reject negative lengths

2017-08-05 Stuart Caie <kyzer@cabextract.org.uk>

* cabd_read_string(): add missing error check on result of read().
Expand Down
10 changes: 8 additions & 2 deletions libmspack/mspack/chmd.c
Expand Up @@ -1269,9 +1269,15 @@ static int read_spaninfo(struct mschm_decompressor_p *self,

/* get the uncompressed length of the LZX stream */
err = read_off64(length_ptr, data, sys, self->d->infh);

sys->free(data);
return (err) ? MSPACK_ERR_DATAFORMAT : MSPACK_ERR_OK;
if (err) return MSPACK_ERR_DATAFORMAT;

if (*length_ptr <= 0) {
D(("output length is invalid"))
return MSPACK_ERR_DATAFORMAT;
}

return MSPACK_ERR_OK;
}

/***************************************
Expand Down
10 changes: 8 additions & 2 deletions libmspack/mspack/lzxd.c
Expand Up @@ -300,8 +300,14 @@ struct lzxd_stream *lzxd_init(struct mspack_system *system,
if (window_bits < 15 || window_bits > 21) return NULL;
}

if (reset_interval < 0 || output_length < 0) {
D(("reset interval or output length < 0"))
return NULL;
}

/* round up input buffer size to multiple of two */
input_buffer_size = (input_buffer_size + 1) & -2;
if (!input_buffer_size) return NULL;
if (input_buffer_size < 2) return NULL;

/* allocate decompression state */
if (!(lzx = (struct lzxd_stream *) system->alloc(system, sizeof(struct lzxd_stream)))) {
Expand Down Expand Up @@ -382,7 +388,7 @@ int lzxd_set_reference_data(struct lzxd_stream *lzx,
}

void lzxd_set_output_length(struct lzxd_stream *lzx, off_t out_bytes) {
if (lzx) lzx->length = out_bytes;
if (lzx && out_bytes > 0) lzx->length = out_bytes;
}

int lzxd_decompress(struct lzxd_stream *lzx, off_t out_bytes) {
Expand Down
3 changes: 2 additions & 1 deletion libmspack/mspack/mszipd.c
Expand Up @@ -349,8 +349,9 @@ struct mszipd_stream *mszipd_init(struct mspack_system *system,

if (!system) return NULL;

/* round up input buffer size to multiple of two */
input_buffer_size = (input_buffer_size + 1) & -2;
if (!input_buffer_size) return NULL;
if (input_buffer_size < 2) return NULL;

/* allocate decompression state */
if (!(zip = (struct mszipd_stream *) system->alloc(system, sizeof(struct mszipd_stream)))) {
Expand Down
1 change: 1 addition & 0 deletions libmspack/mspack/qtmd.c
Expand Up @@ -197,6 +197,7 @@ struct qtmd_stream *qtmd_init(struct mspack_system *system,
/* Quantum supports window sizes of 2^10 (1Kb) through 2^21 (2Mb) */
if (window_bits < 10 || window_bits > 21) return NULL;

/* round up input buffer size to multiple of two */
input_buffer_size = (input_buffer_size + 1) & -2;
if (input_buffer_size < 2) return NULL;

Expand Down

0 comments on commit 6139a0b

Please sign in to comment.