From b16d56bf92cec8713f04d24173bf991295213540 Mon Sep 17 00:00:00 2001
From: James Youngman <jay@gnu.org>
Date: Sun, 15 Aug 2010 12:47:41 +0100
Subject: [PATCH] Fix Savannah bug #30777.
To: findutils-patches@gnu.org

* find/parser.c (insert_exec_ok): Fail if {} appears in an
argument between -exec ... \+ but it's not the whole argument
(that is, reject "FOO{}").  Previously the FOO prefix was accepted
but ignored, which is probably POSIX-incompliant and certainly
surprising.
* find/testsuite/find.posix/sv-bug-30777.exp: New test case for
Savannah bug #30777.
* find/testsuite/Makefile.am (EXTRA_DIST_EXP): Add
find.posix/sv-bug-30777.exp.
---
 ChangeLog                                  |   13 +++++++++++++
 NEWS                                       |    2 ++
 find/parser.c                              |   22 ++++++++++++++++------
 find/testsuite/Makefile.am                 |    1 +
 find/testsuite/find.posix/sv-bug-30777.exp |    6 ++++++
 5 files changed, 38 insertions(+), 6 deletions(-)
 create mode 100644 find/testsuite/find.posix/sv-bug-30777.exp

diff --git a/ChangeLog b/ChangeLog
index 4b3a665..01dc40f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2010-08-15  James Youngman  <jay@gnu.org>
+
+	Fix Savannah bug #30777.
+	* find/parser.c (insert_exec_ok): Fail if {} appears in an
+	argument between -exec ... \+ but it's not the whole argument
+	(that is, reject "FOO{}").  Previously the FOO prefix was accepted
+	but ignored, which is probably POSIX-incompliant and certainly
+	surprising.
+	* find/testsuite/find.posix/sv-bug-30777.exp: New test case for
+	Savannah bug #30777.
+	* find/testsuite/Makefile.am (EXTRA_DIST_EXP): Add
+	find.posix/sv-bug-30777.exp.
+
 2010-05-11  John Gilmore  <gnu@xargs.toad.com>
 
 	Fix bug arising when we receive SIGUSR2.
diff --git a/NEWS b/NEWS
index 7cd5455..64fc0cf 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ GNU findutils NEWS - User visible changes.      -*- outline -*- (allout)
 
 ** Bug Fixes
 
+#30777: find -exec echo TURNIP{} \+ is accepted but TURNIP is eaten
+
 #29828: test suite deadlock on FreeBSD.
 
 ** Translations
diff --git a/find/parser.c b/find/parser.c
index 20d9533..8906510 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -3287,6 +3287,7 @@ insert_exec_ok (const char *action,
   int saw_braces;		/* 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? */
   PRED_FUNC func = entry->pred_func;
   enum BC_INIT_STATUS bcstatus;
 
@@ -3337,7 +3338,7 @@ 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;
+  for (end = start, saw_braces=0, brace_count=0, brace_arg=NULL;
        (argv[end] != NULL)
        && ((argv[end][0] != ';') || (argv[end][1] != '\0'));
        end++)
@@ -3355,6 +3356,7 @@ insert_exec_ok (const char *action,
       if (mbsstr (argv[end], "{}"))
 	{
 	  saw_braces = 1;
+	  brace_arg = argv[end];
 	  ++brace_count;
 
 	  if (0 == end && (func == pred_execdir || func == pred_okdir))
@@ -3384,18 +3386,26 @@ insert_exec_ok (const char *action,
       return false;
     }
 
-  if (our_pred->args.exec_vec.multiple && brace_count > 1)
+  if (our_pred->args.exec_vec.multiple)
     {
-
       const char *suffix;
       if (func == pred_execdir)
 	suffix = "dir";
       else
 	suffix = "";
 
-      error (EXIT_FAILURE, 0,
-	     _("Only one instance of {} is supported with -exec%s ... +"),
-	     suffix);
+      if (brace_count > 1)
+	{
+	  error (EXIT_FAILURE, 0,
+		 _("Only one instance of {} is supported with -exec%s ... +"),
+		 suffix);
+	}
+      else if (strlen (brace_arg) != 2u)
+	{
+	  error (EXIT_FAILURE, 0,
+		 _("In -exec%s ... {} + the {} must appear by itself, but you specified %s"),
+		 suffix, brace_arg);
+	}
     }
 
   /* We use a switch statement here so that the compiler warns us when
diff --git a/find/testsuite/Makefile.am b/find/testsuite/Makefile.am
index 3e4c88d..f8e86ad 100644
--- a/find/testsuite/Makefile.am
+++ b/find/testsuite/Makefile.am
@@ -212,6 +212,7 @@ find.posix/sv-bug-11175.exp \
 find.posix/sv-bug-12181.exp \
 find.posix/sv-bug-25359.exp \
 find.posix/sv-bug-27563-exec.exp \
+find.posix/sv-bug-30777.exp \
 find.posix/depth1.exp \
 find.posix/sizes.exp \
 find.posix/name.exp \
diff --git a/find/testsuite/find.posix/sv-bug-30777.exp b/find/testsuite/find.posix/sv-bug-30777.exp
new file mode 100644
index 0000000..811f727
--- /dev/null
+++ b/find/testsuite/find.posix/sv-bug-30777.exp
@@ -0,0 +1,6 @@
+# tests for Savannah bug 30777 (we accept find -exec ls BLAH{} \+ but the result lacks BLAH)
+# The correct behaviour is to reject this.
+exec rm -rf tmp
+exec mkdir tmp
+find_start f {tmp -exec ls FOO{} \+ }
+exec rm -rf tmp
-- 
1.7.1

