Hi James, thanks, technically this patch fixes it, yet I think it deserves some more love before pushing.
First of all, this patch does not cleanly apply. $ git am /tmp/x.patch Applying: Fix Savannah bug 66365. error: git diff header lacks filename information when removing 1 leading pathname component (line 82) Patch failed at 0001 Fix Savannah bug 66365. ... Didn't you use 'git format-patch -1' and 'git send-email ...'? On 10/31/24 17:28, James Youngman wrote:
From e7641882e3ef373b6c58bcf27fbc49269e2541f3 Mon Sep 17 00:00:00 2001 From: James Youngman <ja...@youngman.org> Date: Thu, 31 Oct 2024 15:06:02 +0000 Subject: [PATCH] [find] Fix Savannah bug 66365.
the bug should be mentioned in the commit message, but the Subject line should better tell about the change, e.g. find: only treat '+' special after pure '{}' in -exec option family
A "+" only terminates -exec when it immediately follows an argument which is exactly "{}".
Let's also explain the change and reasoning for it in a NEWS entry.
--- find/parser.c | 21 ++++++++++++-------
[...]
create mode 100644 find/testsuite/find.posix/sv-bug-66365-exec.exp create mode 100644 find/testsuite/find.posix/sv-bug-66365-exec.xo
I'd prefer going with the newer style for the tests like 'tests/find/exec-plus-last-file.sh'.
diff --git a/find/parser.c b/find/parser.c index ad3b9904..d7b07c40 100644 --- a/find/parser.c +++ b/find/parser.c @@ -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 plus_is_terminator; /* True if previous arg was '{}'. */
I like the change to bool, but I'm not sure whether the new name is clearer here. Actually it should say "the previous argument were pure braces only". Maybe 'saw_pure_braces'?
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,24 +2827,31 @@ 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, plus_is_terminator=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 && plus_is_terminator + && argv[end][0] == '+' && argv[end][1] == 0) { our_pred->args.exec_vec.multiple = 1; break; } - saw_braces = 0; + plus_is_terminator = 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. + */ + plus_is_terminator = true; + }
The indentation is odd.
brace_arg = argv[end]; ++brace_count;
BTW: the guard to prevent '-exec {} ;' seems to be ineffective for a while as well. I'll check. Have a nice day, Berny