Thanks for reporting that. It's a reasonably serious bug. I installed the attached patch to fix it.
From bb77b090006bb941da22efa5095eb347eeef7b91 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Wed, 8 Feb 2017 13:00:11 -0800
Subject: [PATCH] grep: do not mishandle \. in multiple patterns

Problem reported by Lars Wendler (Bug#25655).
* NEWS: Document this.
* src/grep.c (try_fgrep_pattern): Fix typo that prevented
keys from being properly updated.
* tests/foad1: Test for the bug.
---
 NEWS        |  5 +++++
 src/grep.c  | 15 ++++++++-------
 tests/foad1 |  7 +++++++
 3 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/NEWS b/NEWS
index 072b1e9..a3248e4 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,11 @@ GNU grep NEWS                                    -*- outline -*-
 
 ** Bug fixes
 
+  grep without -F no longer goes awry when given two or more patterns
+  that contain no special characters other than '\' and also contain a
+  subpattern like '\.' that escapes a character to make it ordinary.
+  [bug introduced in grep 2.28]
+
   grep no longer fails to build on PCRE versions before 8.20.
   [bug introduced in grep 2.28]
 
diff --git a/src/grep.c b/src/grep.c
index 81654c3..74acb0b 100644
--- a/src/grep.c
+++ b/src/grep.c
@@ -2361,11 +2361,12 @@ try_fgrep_pattern (int matcher, char *keys, size_t *len_p)
   size_t len = *len_p;
   char *new_keys = xmalloc (len + 1);
   char *p = new_keys;
+  char const *q = keys;
   mbstate_t mb_state = { 0 };
 
   while (len != 0)
     {
-      switch (*keys)
+      switch (*q)
         {
         case '$': case '*': case '.': case '[': case '^':
           goto fail;
@@ -2377,7 +2378,7 @@ try_fgrep_pattern (int matcher, char *keys, size_t *len_p)
 
         case '\\':
           if (1 < len)
-            switch (keys[1])
+            switch (q[1])
               {
               case '\n':
               case 'B': case 'S': case 'W': case'\'': case '<':
@@ -2391,7 +2392,7 @@ try_fgrep_pattern (int matcher, char *keys, size_t *len_p)
                   goto fail;
                 /* Fall through.  */
               default:
-                keys++, len--;
+                q++, len--;
                 break;
               }
           break;
@@ -2401,20 +2402,20 @@ try_fgrep_pattern (int matcher, char *keys, size_t *len_p)
         size_t n;
         if (match_icase)
           {
-            int ni = fgrep_icase_charlen (keys, len, &mb_state);
+            int ni = fgrep_icase_charlen (q, len, &mb_state);
             if (ni < 0)
               goto fail;
             n = ni;
           }
         else
           {
-            n = mb_clen (keys, len, &mb_state);
+            n = mb_clen (q, len, &mb_state);
             if (MB_LEN_MAX < n)
               goto fail;
           }
 
-        p = mempcpy (p, keys, n);
-        keys += n;
+        p = mempcpy (p, q, n);
+        q += n;
         len -= n;
       }
     }
diff --git a/tests/foad1 b/tests/foad1
index 286c449..0163f1a 100755
--- a/tests/foad1
+++ b/tests/foad1
@@ -137,6 +137,13 @@ grep_test "$x2" "$y2" -F -w --color=always bc
 grep_test "$x3" "$y3" -E -w --color=always bc
 grep_test "$x3" "$y3" -F -w --color=always bc
 
+# Bug#25655
+grep_test .tar/ .tar/ -e '\.tar' -e '\.tbz'
+grep_test .tar/ .tar/ -o -e '\.tar' -e 'tar'
+grep_test '$*.[^\/' '$*.[^\/' -o -e '\$\*\.\[\^\\' -e abc
+grep_test '$*.[^\/(+?{|/' '$*.[^\/(+?{|/' -o -E \
+          -e '\$\*\.\[\^\\' -e '\(\+\?\{\|'
+
 # Skip the rest of the tests - known to fail. TAA.
 Exit $failures
 
-- 
2.9.3

Reply via email to