Upgrade version to 1.12

This commit is contained in:
YukariChiba 2022-06-11 14:30:52 +08:00
parent 5cc368934a
commit 3429626f5e
No known key found for this signature in database
GPG Key ID: A26F40EFAE3821E2
11 changed files with 8 additions and 911 deletions

View File

@ -1,43 +0,0 @@
From dc9740df61e575e8c3148b7bd3c147a81ea00c7c Mon Sep 17 00:00:00 2001
From: Lasse Collin <lasse.collin@tukaani.org>
Date: Mon, 4 Apr 2022 23:52:49 -0700
Subject: zgrep: avoid exploit via multi-newline file names
* zgrep.in: The issue with the old code is that with multiple
newlines, the N-command will read the second line of input,
then the s-commands will be skipped because it's not the end
of the file yet, then a new sed cycle starts and the pattern
space is printed and emptied. So only the last line or two get
escaped. This patch makes sed read all lines into the pattern
space and then do the escaping.
This vulnerability was discovered by:
cleemy desu wayo working with Trend Micro Zero Day Initiative
---
zgrep.in | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/zgrep.in b/zgrep.in
index 345dae3..bdf7da2 100644
--- a/zgrep.in
+++ b/zgrep.in
@@ -222,9 +222,13 @@ do
'* | *'&'* | *'\'* | *'|'*)
i=$(printf '%s\n' "$i" |
sed '
- $!N
- $s/[&\|]/\\&/g
- $s/\n/\\n/g
+ :start
+ $!{
+ N
+ b start
+ }
+ s/[&\|]/\\&/g
+ s/\n/\\n/g
');;
esac
sed_script="s|^|$i:|"
--
1.8.3.1

View File

@ -1,77 +0,0 @@
From d74a30d45c6834c8e9f87115197370fe86656d81 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering@fb.com>
Date: Mon, 4 Apr 2022 23:52:49 -0700
Subject: zgrep: add NEWS and tests for this exploitable bug
* tests/zgrep-abuse: New file, based on PoC by cleemy desu wayo.
* tests/Makefile.am (TESTS): Add it.
* NEWS: Mention the exploit.
The bug appears to have been present since the beginning.
---
tests/Makefile.am | 1 +
tests/zgrep-abuse | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
create mode 100755 tests/zgrep-abuse
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 18e7c8a..28a1828 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -36,6 +36,7 @@ TESTS = \
z-suffix \
zdiff \
zgrep-f \
+ zgrep-abuse \
zgrep-context \
zgrep-signal \
znew-k
diff --git a/tests/zgrep-abuse b/tests/zgrep-abuse
new file mode 100755
index 0000000..3e8a8f9
--- /dev/null
+++ b/tests/zgrep-abuse
@@ -0,0 +1,41 @@
+#!/bin/sh
+# Show how zgrep applied to a crafted file name may overwrite
+# a selected file with chosen content. Fixed in gzip-1.12.
+
+# Copyright (C) 2022 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+# limit so don't run it by default.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ..
+
+: > z || framework_failure_
+echo test |gzip > 'z|
+p
+1s|.*|chosen-content|
+1w hacked
+etouch .\x2fhacked2
+d
+#
+#' || framework_failure_
+
+fail=0
+
+zgrep test z* > /dev/null
+
+# Before the fix, each of these would be created.
+test -f hacked && fail=1
+test -f hacked2 && fail=1
+
+Exit $fail
--
1.8.3.1

View File

@ -1,46 +0,0 @@
From c99f320d5c0fd98fe88d9cea5407eb7ad9d50e8a Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Mon, 4 Apr 2022 23:52:49 -0700
Subject: zgrep: port to POSIX sed
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* zgrep.in (res): When escaping the file name do not rely on GNU
seds extension to POSIX with respect to s/.../\n/. Instead, use
features that should also work with AIX and/or Solaris sed. This is
simpler anyway, and would have prevented the recently-fixed bug.
---
zgrep.in | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/zgrep.in b/zgrep.in
index bdf7da2..6a16dd1 100644
--- a/zgrep.in
+++ b/zgrep.in
@@ -220,18 +220,11 @@ do
case $i in
(*'
'* | *'&'* | *'\'* | *'|'*)
- i=$(printf '%s\n' "$i" |
- sed '
- :start
- $!{
- N
- b start
- }
- s/[&\|]/\\&/g
- s/\n/\\n/g
- ');;
+ icolon=$(printf '%s\n' "$i:" |
+ sed -e 's/[&\|]/\\&/g' -e '$!s/$/\\/');;
+ (*) icolon="$i:";;
esac
- sed_script="s|^|$i:|"
+ sed_script="s|^|$icolon|"
# Fail if grep or sed fails.
r=$(
--
1.8.3.1

View File

@ -1,73 +0,0 @@
From 5ec23f714e98407a6de25f6f40f125cc87b12908 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 15 Dec 2021 15:04:27 -0800
Subject: [PATCH] doc: document gzip -l change
* NEWS, doc/gzip.texi (Invoking gzip), gzip.1 (gunzip):
Document recent change.
---
doc/gzip.texi | 18 ------------------
gzip.1 | 11 -----------
2 files changed, 29 deletions(-)
diff --git a/doc/gzip.texi b/doc/gzip.texi
index abceb58..48b3485 100644
--- a/doc/gzip.texi
+++ b/doc/gzip.texi
@@ -300,14 +300,6 @@ ratio: compression ratio (0.0% if unknown)
uncompressed_name: name of the uncompressed file
@end example
-The uncompressed size is given as @minus{}1 for files not in @command{gzip}
-format, such as compressed @samp{.Z} files. To get the uncompressed size for
-such a file, you can use:
-
-@example
-zcat file.Z | wc -c
-@end example
-
In combination with the @option{--verbose} option, the following fields are also
displayed:
@@ -323,16 +315,6 @@ With @option{--verbose}, the size totals and compression ratio for all files
is also displayed, unless some sizes are unknown. With @option{--quiet},
the title and totals lines are not displayed.
-The @command{gzip} format represents the input size modulo
-@math{2^32}, so the uncompressed size and compression ratio are listed
-incorrectly for uncompressed files 4 GiB and larger. To work around
-this problem, you can use the following command to discover a large
-uncompressed file's true size:
-
-@example
-zcat file.gz | wc -c
-@end example
-
@item --license
@itemx -L
Display the @command{gzip} license then quit.
diff --git a/gzip.1 b/gzip.1
index 0ae9765..65dea22 100644
--- a/gzip.1
+++ b/gzip.1
@@ -492,17 +492,6 @@ detects that there is extra trailing garbage after the compressed data
and emits a warning by default. You can use the --quiet option to
suppress the warning.
.SH BUGS
-The gzip format represents the input size modulo 2^32, so the
---list option reports incorrect uncompressed sizes and compression
-ratios for uncompressed files 4 GB and larger. To work around this
-problem, you can use the following command to discover a large
-uncompressed file's true size:
-
- zcat file.gz | wc -c
-
-The --list option reports sizes as -1 and crc as ffffffff if the
-compressed file is on a non seekable media.
-
In some rare cases, the --best option gives worse compression than
the default compression level (-6). On some highly redundant files,
.B compress
--
2.27.0

View File

@ -14,15 +14,15 @@ diff --git a/zdiff.in b/zdiff.in
index 067f508..3633398 100644
--- a/zdiff.in
+++ b/zdiff.in
@@ -57,7 +57,7 @@ for arg
@@ -57,7 +57,7 @@
do
case $filesonly$needop$arg in
--h*) printf '%s\n' "$usage" || exit 2; exit;;
- --v*) printf '%s\n' "$version" || exit 2; exit;;
+ --version) printf '%s\n' "$version" || exit 2; exit;;
--) filesonly=t;;
-*\'*) cmp="$cmp '"`printf '%sX\n' "$arg" | sed "$escape"`;;
-*\'*) cmp="$cmp '"`printf '%sX\n' "$arg" | LC_ALL=C sed "$escape"`;;
-[CDFISUWXx]) needop="'$arg'";;
--
--
2.27.0

Binary file not shown.

BIN
gzip-1.12.tar.xz Normal file

Binary file not shown.

View File

@ -1,415 +0,0 @@
From cf26200380585019e927fe3cf5c0ecb7c8b3ef14 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 1 Dec 2021 15:38:02 -0800
Subject: [PATCH] gzip: gzip -l now outputs accurate size
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
gzip -l now decompresses to see how long the uncompressed file was.
This fixes what is by far the most common bug report for gzip.
It has a significant performance cost, but its worth it nowadays.
* gzip.c (main): -l now sets 'test' too. All uses of
'test' changed.
(treat_stdin, treat_file): Call do_list after decompressing,
so that the length is known.
(do_list): Omit arg IFD, since it is no longer needed.
All callers changed. Get the CRC and uncompressed size
from input_crc and bytes_out instead of using lseek.
* tests/list-big: New test.
* unzip.c (unzip): Set unzip_crc before returning.
* util.c (write_buf): If 'test', output nothing.
Update bytes_out with output byte count, regardless of 'test'.
All callers changed.
---
gzip.c | 66 ++++++++++++++++++-----------------------------
gzip.h | 1 +
tests/Makefile.am | 1 +
tests/list-big | 31 ++++++++++++++++++++++
unlzh.c | 5 ++--
unlzw.c | 17 ++++--------
unzip.c | 3 +++
util.c | 18 ++++++-------
8 files changed, 76 insertions(+), 66 deletions(-)
create mode 100755 tests/list-big
diff --git a/gzip.c b/gzip.c
index 735ee0a..ecb19da 100644
--- a/gzip.c
+++ b/gzip.c
@@ -319,7 +319,7 @@ local void discard_input_bytes (size_t nbytes, unsigned int flags);
local int make_ofname (void);
local void shorten_name (char *name);
local int get_method (int in);
-local void do_list (int ifd, int method);
+local void do_list (int method);
local int check_ofname (void);
local void copy_stat (struct stat *ifstat);
local void install_signal_handlers (void);
@@ -535,7 +535,7 @@ int main (int argc, char **argv)
case 'k':
keep = 1; break;
case 'l':
- list = decompress = to_stdout = 1; break;
+ list = decompress = test = to_stdout = 1; break;
case 'L':
license (); finish_out (); break;
case 'm': /* undocumented, may change later */
@@ -655,7 +655,7 @@ int main (int argc, char **argv)
/* And get to work */
if (file_count != 0) {
- if (to_stdout && !test && !list && (!decompress || !ascii)) {
+ if (to_stdout && !test && (!decompress || !ascii)) {
SET_BINARY_MODE (STDOUT_FILENO);
}
while (optind < argc) {
@@ -673,7 +673,7 @@ int main (int argc, char **argv)
{
/* Output any totals, and check for output errors. */
if (!quiet && 1 < file_count)
- do_list (-1, -1);
+ do_list (-1);
if (fflush (stdout) != 0)
write_error ();
}
@@ -759,7 +759,7 @@ local void treat_stdin()
if (decompress || !ascii) {
SET_BINARY_MODE (STDIN_FILENO);
}
- if (!test && !list && (!decompress || !ascii)) {
+ if (!test && (!decompress || !ascii)) {
SET_BINARY_MODE (STDOUT_FILENO);
}
strcpy(ifname, "stdin");
@@ -786,10 +786,6 @@ local void treat_stdin()
do_exit(exit_code); /* error message already emitted */
}
}
- if (list) {
- do_list(ifd, method);
- return;
- }
/* Actually do the compression/decompression. Loop over zipped members.
*/
@@ -805,6 +801,12 @@ local void treat_stdin()
bytes_out = 0; /* required for length check */
}
+ if (list)
+ {
+ do_list (method);
+ return;
+ }
+
if (verbose) {
if (test) {
fprintf(stderr, " OK\n");
@@ -949,7 +951,7 @@ local void treat_file(iname)
/* Generate output file name. For -r and (-t or -l), skip files
* without a valid gzip suffix (check done in make_ofname).
*/
- if (to_stdout && !list && !test) {
+ if (to_stdout && !test) {
strcpy(ofname, "stdout");
} else if (make_ofname() != OK) {
@@ -967,12 +969,6 @@ local void treat_file(iname)
return; /* error message already emitted */
}
}
- if (list) {
- do_list(ifd, method);
- if (close (ifd) != 0)
- read_error ();
- return;
- }
/* If compressing to a file, check if ofname is not ambiguous
* because the operating system truncates names. Otherwise, generate
@@ -992,7 +988,7 @@ local void treat_file(iname)
/* Keep the name even if not truncated except with --no-name: */
if (!save_orig_name) save_orig_name = !no_name;
- if (verbose) {
+ if (verbose && !list) {
fprintf(stderr, "%s:\t", ifname);
}
@@ -1015,6 +1011,12 @@ local void treat_file(iname)
if (close (ifd) != 0)
read_error ();
+ if (list)
+ {
+ do_list (method);
+ return;
+ }
+
if (!to_stdout)
{
copy_stat (&istat);
@@ -1066,7 +1068,7 @@ local void treat_file(iname)
} else {
display_ratio(bytes_in-(bytes_out-header_bytes), bytes_in, stderr);
}
- if (!test && !to_stdout)
+ if (!test)
fprintf(stderr, " -- %s %s", keep ? "created" : "replaced with",
ofname);
fprintf(stderr, "\n");
@@ -1395,7 +1397,8 @@ local int make_ofname()
/* With -t or -l, try all files (even without .gz suffix)
* except with -r (behave as with just -dr).
*/
- if (!recursive && (list || test)) return OK;
+ if (!recursive && test)
+ return OK;
/* Avoid annoying messages with -r */
if (verbose || (!recursive && !quiet)) {
@@ -1688,7 +1691,6 @@ local int get_method(in)
last_member = 1;
if (imagic0 != EOF) {
write_buf (STDOUT_FILENO, magic, 1);
- bytes_out++;
}
}
if (method >= 0) return method;
@@ -1724,9 +1726,8 @@ local int get_method(in)
* If the given method is < 0, display the accumulated totals.
* IN assertions: time_stamp, header_bytes and ifile_size are initialized.
*/
-local void do_list(ifd, method)
- int ifd; /* input file descriptor */
- int method; /* compression method */
+static void
+do_list (int method)
{
ulg crc; /* original crc */
static int first_time = 1;
@@ -1768,26 +1769,9 @@ local void do_list(ifd, method)
return;
}
crc = (ulg)~0; /* unknown */
- bytes_out = -1L;
- bytes_in = ifile_size;
if (method == DEFLATED && !last_member) {
- /* Get the crc and uncompressed size for gzip'ed (not zip'ed) files.
- * If the lseek fails, we could use read() to get to the end, but
- * --list is used to get quick results.
- * Use "gunzip < foo.gz | wc -c" to get the uncompressed size if
- * you are not concerned about speed.
- */
- bytes_in = lseek(ifd, (off_t)(-8), SEEK_END);
- if (bytes_in != -1L) {
- uch buf[8];
- bytes_in += 8L;
- if (read(ifd, (char*)buf, sizeof(buf)) != sizeof(buf)) {
- read_error();
- }
- crc = LG(buf);
- bytes_out = LG(buf+4);
- }
+ crc = unzip_crc;
}
if (verbose)
diff --git a/gzip.h b/gzip.h
index db0305f..ebe3213 100644
--- a/gzip.h
+++ b/gzip.h
@@ -262,6 +262,7 @@ extern int zip (int in, int out);
extern int file_read (char *buf, unsigned size);
/* in unzip.c */
+extern ulg unzip_crc;
extern int unzip (int in, int out);
extern int check_zipfile (int in);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 256bbf7..18e7c8a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -21,6 +21,7 @@ TESTS = \
hufts \
keep \
list \
+ list-big \
memcpy-abuse \
mixed \
null-suffix-clobber \
diff --git a/tests/list-big b/tests/list-big
new file mode 100755
index 0000000..afa3310
--- /dev/null
+++ b/tests/list-big
@@ -0,0 +1,31 @@
+#!/bin/sh
+# Exercise the --list option with a big file.
+
+# Copyright 2021 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+# limit so don't run it by default.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ..
+
+truncate --size 4G big || framework_failure_
+
+gzip -1 big || fail=1
+gzip -l big.gz >out || fail=1
+case $(cat out) in
+ *' 4294967296 '*' big') ;;
+ *) cat out; fail=1;;
+esac
+
+Exit $fail
diff --git a/unlzh.c b/unlzh.c
index 37084fe..f018922 100644
--- a/unlzh.c
+++ b/unlzh.c
@@ -390,9 +390,8 @@ int unlzh(in, out)
decode_start();
while (!done) {
n = decode((unsigned) DICSIZ, window);
- if (!test && n > 0) {
- write_buf(out, (char*)window, n);
- }
+ if (n > 0)
+ write_buf (out, window, n);
}
return OK;
}
diff --git a/unlzw.c b/unlzw.c
index d7714b5..ba824e4 100644
--- a/unlzw.c
+++ b/unlzw.c
@@ -225,10 +225,8 @@ int unlzw(in, out)
"posbits:%ld inbuf:%02X %02X %02X %02X %02X\n",
posbits, p[-1],p[0],p[1],p[2],p[3]);
#endif
- if (!test && outpos > 0) {
- write_buf(out, (char*)outbuf, outpos);
- bytes_out += (off_t)outpos;
- }
+ if (outpos > 0)
+ write_buf (out, outbuf, outpos);
gzip_error (to_stdout
? "corrupt input."
: "corrupt input. Use zcat to recover some data.");
@@ -257,10 +255,7 @@ int unlzw(in, out)
outpos += i;
}
if (outpos >= OUTBUFSIZ) {
- if (!test) {
- write_buf(out, (char*)outbuf, outpos);
- bytes_out += (off_t)outpos;
- }
+ write_buf (out, outbuf, outpos);
outpos = 0;
}
stackp+= i;
@@ -281,9 +276,7 @@ int unlzw(in, out)
}
} while (rsize != 0);
- if (!test && outpos > 0) {
- write_buf(out, (char*)outbuf, outpos);
- bytes_out += (off_t)outpos;
- }
+ if (outpos > 0)
+ write_buf (out, outbuf, outpos);
return OK;
}
diff --git a/unzip.c b/unzip.c
index dacfbaf..b52811e 100644
--- a/unzip.c
+++ b/unzip.c
@@ -51,6 +51,8 @@
/* Globals */
+ulg unzip_crc; /* CRC found by 'unzip'. */
+
static int decrypt; /* flag to turn on decryption */
static int pkzip = 0; /* set for a pkzip file */
static int ext_header = 0; /* set if extended local header */
@@ -210,6 +212,7 @@ int unzip(in, out)
}
}
ext_header = pkzip = 0; /* for next file */
+ unzip_crc = orig_crc;
if (err == OK) return OK;
exit_code = ERROR;
if (!test) abort_gzip();
diff --git a/util.c b/util.c
index 4e73036..cd43886 100644
--- a/util.c
+++ b/util.c
@@ -112,7 +112,6 @@ int copy(in, out)
errno = 0;
while (insize > inptr) {
write_buf(out, (char*)inbuf + inptr, insize - inptr);
- bytes_out += insize - inptr;
got = read_buffer (in, (char *) inbuf, INBUFSIZ);
if (got == -1)
read_error();
@@ -255,9 +254,7 @@ void flush_outbuf()
{
if (outcnt == 0) return;
- if (!test)
- write_buf (ofd, outbuf, outcnt);
- bytes_out += (off_t)outcnt;
+ write_buf (ofd, outbuf, outcnt);
outcnt = 0;
}
@@ -270,16 +267,13 @@ void flush_window()
if (outcnt == 0) return;
updcrc(window, outcnt);
- if (!test) {
- write_buf(ofd, (char *)window, outcnt);
- }
- bytes_out += (off_t)outcnt;
+ write_buf (ofd, window, outcnt);
outcnt = 0;
}
/* ===========================================================================
- * Does the same as write(), but also handles partial pipe writes and checks
- * for error return.
+ * Update the count of output bytes. If testing, do not do any
+ * output. Otherwise, write the buffer, checking for errors.
*/
void write_buf(fd, buf, cnt)
int fd;
@@ -288,6 +282,10 @@ void write_buf(fd, buf, cnt)
{
unsigned n;
+ bytes_out += cnt;
+ if (test)
+ return;
+
while ((n = write_buffer (fd, buf, cnt)) != cnt) {
if (n == (unsigned)(-1)) {
write_error();
--
2.27.0

View File

@ -1,24 +1,15 @@
Name: gzip
Version: 1.11
Release: 4
Version: 1.12
Release: 1
Summary: A data compression utility
License: GPLv3
URL: https://www.gnu.org/software/gzip
Source0: https://ftp.gnu.org/gnu/gzip/gzip-%{version}.tar.xz
Patch6000: gzip-l-now-outputs-accurate-size.patch
Patch6001: doc-document-gzip-l-change.patch
Patch6002: zdiff-fix-arg-handling-bug.patch
Patch6003: zdiff-fix-another-arg-handling-bug.patch
Patch9000: fix-verbose-disable.patch
Patch9001: performance-neoncrc32-and-prfm.patch
Patch6004: backport-0001-CVE-2022-1271.patch
Patch6005: backport-0002-CVE-2022-1271.patch
Patch6006: backport-0003-CVE-2022-1271.patch
BuildRequires: gcc texinfo less autoconf automake
Requires: coreutils
Conflicts: filesystem < 3
@ -67,6 +58,9 @@ make check
%{_mandir}/man1/*
%changelog
* Sat Jun 11 2022 YukariChiba <i@0x7f.cc> - 1.12-1
- Upgrade version.
* Tue May 24 2022 loong_C <loong_c@yeah.net> - 1.11-4
- fix changelog date

View File

@ -1,200 +0,0 @@
From 78b29bdde523b72748049f3cf05698b9dabf52ae Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Tue, 8 Mar 2022 13:02:37 -0800
Subject: [PATCH 2/2] zdiff: fix another arg-handling bug
Also allow args after file names.
Problem reported by Lv Ying <https://bugs.gnu.org/54290#12>.
---
zdiff.in | 127 ++++++++++++++++++++++++++++++++-----------------------
1 file changed, 75 insertions(+), 52 deletions(-)
diff --git a/zdiff.in b/zdiff.in
index d982d9f..593cb6e 100644
--- a/zdiff.in
+++ b/zdiff.in
@@ -48,60 +48,85 @@ escape='
$s/X$/'\''/
'
-while :; do
- argdone=:
- case $1 in
+filesonly=
+file1=
+file2=
+needop=
+
+for arg
+do
+ case $filesonly$needop$arg in
--h*) printf '%s\n' "$usage" || exit 2; exit;;
--v*) printf '%s\n' "$version" || exit 2; exit;;
- --) shift; break;;
- -*\'*) argdone=false arg=$1;;
- -[CDFISUWXx])
- cmp="$cmp $1"
- case ${2?} in
- -*\'*) argdone=false arg=$2;;
- *) cmp="$cmp '$2'";;
- esac
- shift;;
- -?*) cmp="$cmp '$1'";;
- *) break;;
+ --) filesonly=t;;
+ -*\'*) cmp="$cmp '"`printf '%sX\n' "$arg" | sed "$escape"`;;
+ -[CDFISUWXx]) needop="'$arg'";;
+ -?*) cmp="$cmp '$arg'";;
+ *) case $needop in
+ '') case $arg in
+ '') printf >&2 '%s\n' "$0: empty file name"; exit 2;;
+ esac
+ case $file1 in
+ '') file1=$arg;;
+ *) case $file2 in
+ '') file2=$arg;;
+ *) printf >&2 '%s\n' "$0: extra operand '$arg'"; exit 2;;
+ esac;;
+ esac;;
+ *) cmp="$cmp $needop '$arg'"
+ needop=;;
+ esac;;
esac
- $argdone || cmp="$cmp '"`printf '%sX\n' "$arg" | sed "$escape"`
- shift
done
+case $needop in
+'') ;;
+*) printf >&2 '%s\n' "$0: $prevarg: option requires an argument -- $needop"
+ exit 2;;
+esac
+
cmp="$cmp --"
-for file
-do
- test "X$file" = X- || <"$file" || exit 2
-done
+case $file1 in
+'') printf >&2 '%s\n' "$0: missing operand"; exit 2;;
+-) ;;
+*) <"$file1" || exit 2;;
+esac
+case $file2 in
+''|-) ;;
+*) <"$file2" || exit 2;;
+esac
gzip_status=0
exec 3>&1
-if test $# -eq 1; then
- case $1 in
+case $file2 in
+'')
+ case $file1 in
*[-.]gz* | *[-.][zZ] | *.t[ga]z)
- FILE=`expr "X$1" : 'X\(.*\)[-.][zZtga]*$'`
+ FILE=`expr "X$file1" : 'X\(.*\)[-.][zZtga]*$'`
gzip_status=$(
exec 4>&1
- (gzip -cd -- "$1" 4>&-; echo $? >&4) 3>&- | eval "$cmp" - '"$FILE"' >&3
+ (gzip -cd -- "$file1" 4>&-; echo $? >&4) 3>&- |
+ eval "$cmp" - '"$FILE"' >&3
);;
*)
- printf >&2 '%s\n' "$0: $1: unknown compressed file extension"
+ printf >&2 '%s\n' "$0: $file1: unknown compressed file extension"
exit 2;;
- esac
-elif test $# -eq 2; then
- case "$1" in
+ esac;;
+*)
+ case $file1,$file2 in
+ -,-)
+ gzip_status=$(
+ exec 4>&1
+ (gzip -cdfq - 4>&-; echo $? >&4) 3>&- |
+ eval "$cmp" - - >&3
+ );;
+ *)
+ case $file1 in
*[-.]gz* | *[-.][zZ] | *.t[ga]z | -)
- case "$2" in
+ case $file2 in
*[-.]gz* | *[-.][zZ] | *.t[ga]z | -)
- if test "$1$2" = --; then
- gzip_status=$(
- exec 4>&1
- (gzip -cdfq - 4>&-; echo $? >&4) 3>&- |
- eval "$cmp" - - >&3
- )
- elif
+ if
# Reject Solaris 8's buggy /bin/bash 2.03.
echo X |
(echo X | eval "$cmp" /dev/fd/5 - >/dev/null 2>&1) \
@@ -109,8 +134,9 @@ elif test $# -eq 2; then
then
gzip_status=$(
exec 4>&1
- (gzip -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
- ( (gzip -cdfq -- "$2" 4>&-; echo $? >&4) 3>&- 5<&- </dev/null |
+ (gzip -cdfq -- "$file1" 4>&-; echo $? >&4) 3>&- |
+ ((gzip -cdfq -- "$file2" 4>&-
+ echo $? >&4) 3>&- 5<&- </dev/null |
eval "$cmp" /dev/fd/5 - >&3) 5<&0
)
cmp_status=$?
@@ -137,10 +163,10 @@ elif test $# -eq 2; then
set -C
tmp=${TMPDIR}zdiff$$
fi
- gzip -cdfq -- "$2" > "$tmp" || exit 2
+ gzip -cdfq -- "$file2" > "$tmp" || exit 2
gzip_status=$(
exec 4>&1
- (gzip -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
+ (gzip -cdfq -- "$file1" 4>&-; echo $? >&4) 3>&- |
eval "$cmp" - '"$tmp"' >&3
)
cmp_status=$?
@@ -151,25 +177,22 @@ elif test $# -eq 2; then
*)
gzip_status=$(
exec 4>&1
- (gzip -cdfq -- "$1" 4>&-; echo $? >&4) 3>&- |
- eval "$cmp" - '"$2"' >&3
+ (gzip -cdfq -- "$file1" 4>&-; echo $? >&4) 3>&- |
+ eval "$cmp" - '"$file2"' >&3
);;
esac;;
- *) case "$2" in
+ *) case $file2 in
*[-.]gz* | *[-.][zZ] | *.t[ga]z | -)
gzip_status=$(
exec 4>&1
- (gzip -cdfq -- "$2" 4>&-; echo $? >&4) 3>&- |
- eval "$cmp" '"$1"' - >&3
+ (gzip -cdfq -- "$file2" 4>&-; echo $? >&4) 3>&- |
+ eval "$cmp" '"$file1"' - >&3
);;
- *) eval "$cmp" '"$1"' '"$2"';;
+ *) eval "$cmp" '"$file1"' '"$file2"';;
esac;;
- esac
-else
- printf >&2 '%s\n' \
- "$0: invalid number of operands; try \`$0 --help' for help"
- exit 2
-fi
+ esac;;
+ esac;;
+esac
cmp_status=$?
test "$gzip_status" -eq 0 || exit 2
--
2.27.0

View File

@ -1,43 +0,0 @@
From 9cd9a789c186bfe6594c0aed8ba34c9e3d9d9292 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Mon, 7 Mar 2022 09:38:08 -0800
Subject: [PATCH] zdiff: fix arg handling bug
Problem reported by Lv Ying (Bug#54291).
* zdiff.in (escape): Handle args like '-C 5'.
---
zdiff.in | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/zdiff.in b/zdiff.in
index a1325f2..a72d08d 100644
--- a/zdiff.in
+++ b/zdiff.in
@@ -49,14 +49,23 @@ escape='
'
while :; do
+ argdone=:
case $1 in
--h*) printf '%s\n' "$usage" || exit 2; exit;;
--v*) printf '%s\n' "$version" || exit 2; exit;;
--) shift; break;;
- -*\'*) cmp="$cmp '"`printf '%sX\n' "$1" | sed "$escape"`;;
+ -*\'*) argdone=false arg=$1;;
+ -[CDFISUWXx])
+ cmp="$cmp $1"
+ case ${2?} in
+ -*\'*) argdone=false arg=$2;;
+ *) cmp="$cmp '$2'";;
+ esac
+ shift;;
-?*) cmp="$cmp '$1'";;
*) break;;
esac
+ $argdone || cmp="$cmp '"`printf '%sX\n' "$arg" | sed "$escape"`
shift
done
cmp="$cmp --"
--
2.27.0