Commit 102ea0ed for xz

commit 102ea0ed1290869f3af53009f98def030c6b6cd0
Author: xordanblu <jordygarciamorales@gmail.com>
Date:   Sat Aug 15 19:50:05 2026 +0300

    xz: Make it an error if the totals in xz --list exceed UINT64_MAX

    If at least three files are passed to xz --list, the totals might exceed
    the range of uint64_t. Previously wrong totals were displayed in this
    case. Now an error is shown as soon as an overflow would occur, and the
    remaining files aren't processed. In most other cases an error doesn't
    prevent xz from processing the remaining files, but in this case it
    feels OK because (1) the error should be very rare, (2) it keeps the
    code slightly simpler, and (3) with xz --robot --list the caller will
    likely ignore the output anyway when xz exits with a non-zero status.

    Co-authored-by: Lasse Collin <lasse.collin@tukaani.org>
    Fixes: https://github.com/tukaani-project/xz/pull/240

diff --git a/src/xz/list.c b/src/xz/list.c
index 210f23ad..56744829 100644
--- a/src/xz/list.c
+++ b/src/xz/list.c
@@ -1142,12 +1142,36 @@ print_info_robot(xz_file_info *xfi, file_pair *pair)
 static void
 update_totals(const xz_file_info *xfi)
 {
-	// TODO: Integer overflow checks
+	const uint64_t streams = lzma_index_stream_count(xfi->idx);
+	const uint64_t blocks = lzma_index_block_count(xfi->idx);
+	const uint64_t compressed_size = lzma_index_file_size(xfi->idx);
+	const uint64_t uncompressed_size
+			= lzma_index_uncompressed_size(xfi->idx);
+
+	// Of these, totals.uncompressed_size is the most likely to overflow
+	// because it doesn't require a huge file. Even that is likely to
+	// happen only with invalid/crafted files.
+	//
+	// For simplicity, the error message refers to file sizes even though
+	// we are checking other things too.
+	if (totals.files == UINT64_MAX
+			|| UINT64_MAX - totals.streams < streams
+			|| UINT64_MAX - totals.blocks < blocks
+			|| UINT64_MAX - totals.compressed_size
+				< compressed_size
+			|| UINT64_MAX - totals.uncompressed_size
+				< uncompressed_size
+			|| UINT64_MAX - totals.stream_padding
+				< xfi->stream_padding) {
+		message_fatal(_("Error: The total compressed or uncompressed "
+				"size of the files is too large"));
+	}
+
 	++totals.files;
-	totals.streams += lzma_index_stream_count(xfi->idx);
-	totals.blocks += lzma_index_block_count(xfi->idx);
-	totals.compressed_size += lzma_index_file_size(xfi->idx);
-	totals.uncompressed_size += lzma_index_uncompressed_size(xfi->idx);
+	totals.streams += streams;
+	totals.blocks += blocks;
+	totals.compressed_size += compressed_size;
+	totals.uncompressed_size += uncompressed_size;
 	totals.stream_padding += xfi->stream_padding;
 	totals.checks |= lzma_index_checks(xfi->idx);