mirror of
git://git.sv.gnu.org/findutils.git
synced 2026-01-28 20:43:21 +01:00
find: -exec is terminated by + only if the prior arg is exactly '{}'
A "+" only terminates -exec when it immediately follows an argument
which is exactly "{}" (and not, for example, "{}x"). This fixes
Savannah bug 66365.
* NEWS: explain this change.
* doc/find.texi: update one place which omitted the '{}' before '+'.
* find/parser.c (insert_exec_ok): consider + to be special ony if it
follows an argument which is exactly '{}'.
* tests/find/sv-bug-66365-exec.sh: test for this bug.
* tests/local.mk: add the new test file.
This commit is contained in:
6
NEWS
6
NEWS
@@ -7,6 +7,12 @@ GNU findutils NEWS - User visible changes. -*- outline -*- (allout)
|
||||
'find -ignore_readdir_race' now has a race between FTS read and the visiting
|
||||
of the entry when the file was removed. [#45930]
|
||||
|
||||
To fix a POSIX compatibility bug, -exec foo Z{} + is no longer a
|
||||
complete predicate, because '+' is only a terminator when it follows
|
||||
an argument which is exactly '{}'. The findutils documentation
|
||||
already states this, and now find's behaviour matches the
|
||||
documentation.
|
||||
|
||||
** Documentation Changes
|
||||
|
||||
The forthcoming Issue 8 of the POSIX standard will standardise "find
|
||||
|
||||
@@ -1536,7 +1536,7 @@ This is different to @samp{-prune} because @samp{-prune} only applies
|
||||
to the contents of pruned directories, while @samp{-quit} simply makes
|
||||
@code{find} stop immediately. No child processes will be left
|
||||
running. Any command lines which have been built by @samp{-exec
|
||||
... \+} or @samp{-execdir ... \+} are invoked before the program is
|
||||
... @{@} +} or @samp{-execdir ... \+} are invoked before the program is
|
||||
exited. After @samp{-quit} is executed, no more files specified on
|
||||
the command line will be processed. For example, @samp{find /tmp/foo
|
||||
/tmp/bar -print -quit} will print only @samp{/tmp/foo}. One common
|
||||
|
||||
@@ -2770,7 +2770,7 @@ insert_exec_ok (const char *action,
|
||||
{
|
||||
int start, end; /* Indexes in ARGV of start & end of cmd. */
|
||||
int i; /* Index into cmd args */
|
||||
int saw_braces; /* True if previous arg was '{}'. */
|
||||
bool prev_was_braces_only; /* Previous arg was '{}' (not e.g. 'Q' or '{}x'). */
|
||||
bool allow_plus; /* True if + is a valid terminator */
|
||||
int brace_count; /* Number of instances of {}. */
|
||||
const char *brace_arg; /* Which arg did {} appear in? */
|
||||
@@ -2827,28 +2827,35 @@ insert_exec_ok (const char *action,
|
||||
* Also figure out if the command is terminated by ";" or by "+".
|
||||
*/
|
||||
start = *arg_ptr;
|
||||
for (end = start, saw_braces=0, brace_count=0, brace_arg=NULL;
|
||||
for (end = start, prev_was_braces_only=false, brace_count=0, brace_arg=NULL;
|
||||
(argv[end] != NULL)
|
||||
&& ((argv[end][0] != ';') || (argv[end][1] != '\0'));
|
||||
end++)
|
||||
{
|
||||
/* For -exec and -execdir, "{} +" can terminate the command. */
|
||||
if ( allow_plus
|
||||
&& argv[end][0] == '+' && argv[end][1] == 0
|
||||
&& saw_braces)
|
||||
if (allow_plus && prev_was_braces_only
|
||||
&& argv[end][0] == '+' && argv[end][1] == 0)
|
||||
{
|
||||
our_pred->args.exec_vec.multiple = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
saw_braces = 0;
|
||||
prev_was_braces_only = false;
|
||||
if (mbsstr (argv[end], "{}"))
|
||||
{
|
||||
saw_braces = 1;
|
||||
if (0 == strcmp(argv[end], "{}"))
|
||||
{
|
||||
/* Savannah bug 66365: + only terminates the predicate
|
||||
* immediately after an argument which is exactly, "{}".
|
||||
* However, the "{}" in "x{}" should get expanded for
|
||||
* the ";" case.
|
||||
*/
|
||||
prev_was_braces_only = true;
|
||||
}
|
||||
brace_arg = argv[end];
|
||||
++brace_count;
|
||||
|
||||
if (0 == end && (func == pred_execdir || func == pred_okdir))
|
||||
if (start == end && (func == pred_execdir || func == pred_okdir))
|
||||
{
|
||||
/* The POSIX standard says that {} replacement should
|
||||
* occur even in the utility name. This is insecure
|
||||
|
||||
27
tests/find/sv-bug-66365-exec.sh
Normal file
27
tests/find/sv-bug-66365-exec.sh
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
# Test that find -exec ... + treats the + as a terminator only when it
|
||||
# immediately follows a {}. See Savannah bug #66365.
|
||||
|
||||
# Copyright (C) 2024 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/>.
|
||||
|
||||
. "${srcdir=.}/tests/init.sh"; fu_path_prepend_
|
||||
print_ver_ find
|
||||
|
||||
find . -prune -exec echo x{} + \; >| out
|
||||
echo 'x. +' >| exp || framework_failure_
|
||||
compare exp out || fail=1
|
||||
|
||||
Exit $fail
|
||||
@@ -130,6 +130,7 @@ sh_tests = \
|
||||
tests/find/used.sh \
|
||||
tests/find/newer.sh \
|
||||
tests/find/opt-numeric-arg.sh \
|
||||
tests/find/sv-bug-66365-exec.sh \
|
||||
tests/find/user-group-max.sh \
|
||||
tests/xargs/conflicting_opts.sh \
|
||||
tests/xargs/verbose-quote.sh \
|
||||
|
||||
Reference in New Issue
Block a user