Thanks for reporting and diagnosing that gzip bug. I installed the
attached patch to fix it, and to add a regression test.From 607bc945230c9fdcad24527578bf3605f446dc7c Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Mon, 8 Jan 2024 20:39:05 -0800
Subject: [PATCH] gzip: fix -l bug with multimember files
Problem reported by Antonio Diaz Diaz in:
https://lists.gnu.org/r/bug-gzip/2024-01/msg00000.html
* NEWS: Mention this.
* gzip.c (treat_stdin, treat_file): Do not clear bytes_out.
* tests/list: Test for the bug.
* unpack.c (unpack):
* unzip.c (unzip):
Do not assume bytes_out is initially zero.
---
NEWS | 5 +++++
gzip.c | 2 --
tests/list | 9 +++++++++
unpack.c | 3 ++-
unzip.c | 3 ++-
5 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/NEWS b/NEWS
index b20e582..0a95e7f 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,11 @@ GNU gzip NEWS -*- outline -*-
* Noteworthy changes in release ?.? (????-??-??) [?]
+** Bug fixes
+
+ 'gzip -l' no longer misreports lengths of multimember inputs.
+ [bug introduced in gzip-1.12]
+
* Noteworthy changes in release 1.13 (2023-08-19) [stable]
diff --git a/gzip.c b/gzip.c
index 35cb662..b61887d 100644
--- a/gzip.c
+++ b/gzip.c
@@ -788,7 +788,6 @@ treat_stdin ()
method = get_method(ifd);
if (method < 0) return; /* error message already emitted */
- bytes_out = 0; /* required for length check */
}
if (list)
@@ -995,7 +994,6 @@ treat_file (char *iname)
method = get_method(ifd);
if (method < 0) break; /* error message already emitted */
- bytes_out = 0; /* required for length check */
}
if (close (ifd) != 0)
diff --git a/tests/list b/tests/list
index 85478d2..98057bb 100755
--- a/tests/list
+++ b/tests/list
@@ -28,4 +28,13 @@ gzip -l in.gz >out1 || fail=1
gzip -l in.gz | cat >out2 || fail=1
compare out1 out2 || fail=1
+echo '' >small || framework_failure_
+gzip small || fail=1
+cat small.gz small.gz >smallx2.gz || framework_failure_
+gzip -l smallx2.gz >smallout || fail=1
+case $(cat smallout) in
+ *' 2 '*' smallx2') ;;
+ *) cat smallout; fail=1;;
+esac
+
Exit $fail
diff --git a/unpack.c b/unpack.c
index d192067..9b178ba 100644
--- a/unpack.c
+++ b/unpack.c
@@ -221,6 +221,7 @@ unpack (int in, int out)
unsigned eob; /* End Of Block code */
register unsigned peek; /* lookahead bits */
unsigned peek_mask; /* Mask for peek_bits bits */
+ off_t orig_bytes_out = bytes_out;
ifd = in;
ofd = out;
@@ -266,7 +267,7 @@ unpack (int in, int out)
} /* for (;;) */
flush_window();
- if (orig_len != (ulg)(bytes_out & 0xffffffff)) {
+ if (orig_len != (ulg)((bytes_out - orig_bytes_out) & 0xffffffff)) {
gzip_error ("invalid compressed data--length error");
}
return OK;
diff --git a/unzip.c b/unzip.c
index 9b22101..07c9027 100644
--- a/unzip.c
+++ b/unzip.c
@@ -117,6 +117,7 @@ unzip (int in, int out)
{
ulg orig_crc = 0; /* original crc */
ulg orig_len = 0; /* original uncompressed length */
+ off_t orig_bytes_out = bytes_out;
int n;
uch buf[EXTHDR]; /* extended local header */
int err = OK;
@@ -194,7 +195,7 @@ unzip (int in, int out)
program_name, ifname);
err = ERROR;
}
- if (orig_len != (ulg)(bytes_out & 0xffffffff)) {
+ if (orig_len != (ulg)((bytes_out - orig_bytes_out) & 0xffffffff)) {
fprintf(stderr, "\n%s: %s: invalid compressed data--length error\n",
program_name, ifname);
err = ERROR;
--
2.40.1