summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2022-04-05 15:16:33 -0700
committerJim Meyering <meyering@fb.com>2022-04-07 09:28:24 -0700
commit9d3248751178939713a39115cf68ec8a11506cc9 (patch)
tree08cfc5cbb2a4d97046118a0507afe4518e721fa3
parent5e1fc8b92c1af9382365aef0f9130341ee1d2c76 (diff)
downloadgzip-9d3248751178939713a39115cf68ec8a11506cc9.tar.gz
zgrep: fix "binary file matches" mislabeling
Problem reported by Jim Avera (Bug#31280). This became more of an issue when GNU grep 3.5 (2020) started sending "binary file matches" diagnostics to stderr instead of to stdout. * tests/Makefile.am (TESTS): Add zgrep-binary. * tests/zgrep-binary: New test. * zgrep.in (args): New var, to accumulate args separately from grep command, so we can prepend args if need be. Most uses of 'grep' changed to use 'args' instead, or also. (with_filename): Set to 1 if more than one file and -h not given; this simplifies later code. (gnuish_grep): New var; evaluates to true if grep supports -H and --label options, as is true for GNU and FreeBSD grep. Append -H to 'grep' if outputting file names with GNUish grep, and use --label with GNUish grep unless reading from stdin, as that’s safer and more efficient than relabeling with 'sed'.
-rw-r--r--NEWS3
-rw-r--r--tests/Makefile.am1
-rwxr-xr-xtests/zgrep-binary30
-rw-r--r--zgrep.in28
4 files changed, 53 insertions, 9 deletions
diff --git a/NEWS b/NEWS
index 6f83b6a..c15d2e0 100644
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,9 @@ GNU gzip NEWS -*- outline -*-
can no longer overwrite an arbitrary, attacker-selected file.
[bug introduced in gzip-1.3.10]
+ zgrep now names input file on error instead of mislabeling it as
+ "(standard input)", if grep supports the GNU -H and --label options.
+
'zdiff -C 5' no longer misbehaves by treating '5' as a file name.
[bug present since the beginning]
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5f148d6..b116b03 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -37,6 +37,7 @@ TESTS = \
zdiff \
zgrep-f \
zgrep-abuse \
+ zgrep-binary \
zgrep-context \
zgrep-signal \
znew-k
diff --git a/tests/zgrep-binary b/tests/zgrep-binary
new file mode 100755
index 0000000..6c00cef
--- /dev/null
+++ b/tests/zgrep-binary
@@ -0,0 +1,30 @@
+#!/bin/sh
+# 'zgrep PATTERN FILE' would output "(standard input): binary file matches"
+# without mentioning FILE. 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_ ..
+
+fail=0
+
+unset GREP_OPTIONS
+
+printf 'foo\0\n' >f || framework_failure_
+LC_ALL=C zgrep foo f >out 2>err && grep '(standard input)' out err && fail=1
+
+Exit $fail
diff --git a/zgrep.in b/zgrep.in
index 2cb2426..25c2782 100644
--- a/zgrep.in
+++ b/zgrep.in
@@ -23,6 +23,7 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
grep='${GREP-'\''@GREP@'\''}'
+args=
version='zgrep (gzip) @VERSION@
Copyright (C) 2010-2018 Free Software Foundation, Inc.
@@ -178,7 +179,7 @@ while test $# -ne 0; do
option="'$option'";;
esac
- grep="$grep $option$optarg"
+ args="$args $option$optarg"
done
eval "set -- $operands "'${1+"$@"}'
@@ -186,15 +187,23 @@ eval "set -- $operands "'${1+"$@"}'
if test $have_pat -eq 0; then
case ${1?"missing pattern; try \`$0 --help' for help"} in
(*\'*)
- grep="$grep -- '"$(printf '%s\n' "$1" | LC_ALL=C sed "$escape");;
+ args="$args -- '"$(printf '%s\n' "$1" | LC_ALL=C sed "$escape");;
(*)
- grep="$grep -- '$1'";;
+ args="$args -- '$1'";;
esac
shift
fi
if test $# -eq 0; then
set -- -
+elif test 1 -lt $# && test $no_filename -eq 0; then
+ with_filename=1
+fi
+
+l_e=$(eval "(echo e | $grep -H --label=l e) 2>/dev/null") && test "$l_e" = l:e
+gnuish_grep="test $? -eq 0"
+if $gnuish_grep && test $with_filename -eq 1; then
+ grep="$grep -H"
fi
exec 3>&1
@@ -207,9 +216,9 @@ do
exec 5>&1
('gzip' -cdfq -- "$i" 5>&-; echo $? >&5) 3>&- |
if test $files_with_matches -eq 1; then
- eval "$grep" >/dev/null && { printf '%s\n' "$i" || exit 2; }
+ eval "$grep$args" >/dev/null && { printf '%s\n' "$i" || exit 2; }
elif test $files_without_matches -eq 1; then
- eval "$grep" >/dev/null || {
+ eval "$grep$args" >/dev/null || {
r=$?
if test $r -eq 1; then
printf '%s\n' "$i" || r=2
@@ -217,9 +226,10 @@ do
test 256 -le $r && r=$(expr 128 + $r % 128)
exit $r
}
- elif test $with_filename -eq 0 &&
- { test $# -eq 1 || test $no_filename -eq 1; }; then
- eval "$grep"
+ elif $gnuish_grep && test "$i" != -; then
+ eval "$grep --label \"\$i\"$args"
+ elif $gnuish_grep || test $with_filename -eq 0; then
+ eval "$grep$args"
else
case $i in
(*'
@@ -233,7 +243,7 @@ do
# Fail if grep or sed fails.
r=$(
exec 4>&1
- (eval "$grep" 4>&-; echo $? >&4) 3>&- |
+ (eval "$grep$args" 4>&-; echo $? >&4) 3>&- |
LC_ALL=C sed "$sed_script" >&3 4>&-
) || { r=$?; test $r -lt 2 && r=2; }
test 256 -le $r && r=$(expr 128 + $r % 128)