>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.

A "+" only terminates -exec when it immediately follows an argument
which is exactly "{}".
---
 find/parser.c                                 | 21 ++++++++++++-------
 find/testsuite/Makefile.am                    |  2 ++
 .../find.posix/sv-bug-66365-exec.exp          |  5 +++++
 .../testsuite/find.posix/sv-bug-66365-exec.xo |  1 +
 4 files changed, 22 insertions(+), 7 deletions(-)
 create mode 100644 find/testsuite/find.posix/sv-bug-66365-exec.exp
 create mode 100644 find/testsuite/find.posix/sv-bug-66365-exec.xo

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 '{}'. */
   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;
+     }
           brace_arg = argv[end];
           ++brace_count;

diff --git a/find/testsuite/Makefile.am b/find/testsuite/Makefile.am
index ed2962a2..ffa5749c 100644
--- a/find/testsuite/Makefile.am
+++ b/find/testsuite/Makefile.am
@@ -105,6 +105,7 @@ find.posix/sv-bug-11175.xo \
 find.posix/sv-bug-12181.xo \
 find.posix/sv-bug-25359.xo \
 find.posix/sv-bug-27563-exec.xo \
+find.posix/sv-bug-66365-exec.xo \
 find.posix/mtime0.xo \
 find.posix/sizes.xo \
 find.posix/name.xo \
@@ -245,6 +246,7 @@ find.posix/sv-bug-15235.exp \
 find.posix/sv-bug-19605.exp \
 find.posix/sv-bug-19613.exp \
 find.posix/sv-bug-19617.exp \
+find.posix/sv-bug-66365-exec.exp \
 find.posix/typesize.exp \
 find.posix/user-empty.exp \
 find.posix/user-missing.exp
diff --git a/find/testsuite/find.posix/sv-bug-66365-exec.exp
b/find/testsuite/find.posix/sv-bug-66365-exec.exp
new file mode 100644
index 00000000..ef88762e
--- /dev/null
+++ b/find/testsuite/find.posix/sv-bug-66365-exec.exp
@@ -0,0 +1,5 @@
+# tests for Savannah bug 66365 (result of find . -prune -exec echo x{} + \;)
+exec rm -rf tmp
+exec mkdir tmp
+find_start p {tmp -prune -exec echo x\{\} + \; }
+exec rm -rf tmp
diff --git a/find/testsuite/find.posix/sv-bug-66365-exec.xo
b/find/testsuite/find.posix/sv-bug-66365-exec.xo
new file mode 100644
index 00000000..eb46b7d3
--- /dev/null
+++ b/find/testsuite/find.posix/sv-bug-66365-exec.xo
@@ -0,0 +1 @@
+xtmp +
-- 
2.39.5

Reply via email to