From c8cace3d6e965c0fb537591372bf71b9357dd76c Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Mon, 24 Jun 2019 20:45:49 +0300 Subject: xz: Fix an integer overflow with 32-bit off_t. Or any off_t which isn't very big (like signed 64 bit integer that most system have). A small off_t could overflow if the file being decompressed had long enough run of zero bytes, which would result in corrupt output. --- src/xz/file_io.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/xz/file_io.c') diff --git a/src/xz/file_io.c b/src/xz/file_io.c index 2352b297..6db62e76 100644 --- a/src/xz/file_io.c +++ b/src/xz/file_io.c @@ -1273,8 +1273,15 @@ io_write(file_pair *pair, const io_buf *buf, size_t size) // if the file ends with sparse block, we must also return // if size == 0 to avoid doing the lseek(). if (size == IO_BUFFER_SIZE) { - if (is_sparse(buf)) { - pair->dest_pending_sparse += size; + // Even if the block was sparse, treat it as non-sparse + // if the pending sparse amount is large compared to + // the size of off_t. In practice this only matters + // on 32-bit systems where off_t isn't always 64 bits. + const off_t pending_max + = (off_t)(1) << (sizeof(off_t) * CHAR_BIT - 2); + if (is_sparse(buf) && pair->dest_pending_sparse + < pending_max) { + pair->dest_pending_sparse += (off_t)(size); return false; } } else if (size == 0) { -- cgit v1.2.3