Subject: bug#22655: [PATCH] grep: -Pz no longer misdiagnoses [^a]

From: Paul Eggert <[email-masked]>
Date: Wed, 23 Mar 2016 09:03:01 -0700

Problem reported by Michael Jess.
* NEWS: Document this.
* src/pcresearch.c (Pcompile): Do not diagnose [^ when [ is unescaped.
* tests/pcre: Test for the bug.
---
 NEWS             | 3 +++
 src/pcresearch.c | 8 +++++---
 tests/pcre       | 1 +
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index 144f668..69e4a23 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,9 @@ GNU grep NEWS                                    -*- outline -*-
 
 ** Bug fixes
 
+  grep -Pz no longer mistakenly diagnoses patterns like [^a] that use
+  negated character classes. [bug introduced in grep-2.24]
+
   grep -oz now uses null bytes, not newlines, to terminate output lines.
   [bug introduced in grep-2.5]
 
diff --git a/src/pcresearch.c b/src/pcresearch.c
index 3b8e795..f6e72b0 100644
--- a/src/pcresearch.c
+++ b/src/pcresearch.c
@@ -127,15 +127,17 @@ Pcompile (char const *pattern, size_t size)
   if (! eolbyte)
     {
       bool escaped = false;
+      bool after_unescaped_left_bracket = false;
       for (p = pattern; *p; p++)
         if (escaped)
-          escaped = false;
+          escaped = after_unescaped_left_bracket = false;
         else
           {
-            escaped = *p == '\\';
-            if (*p == '^' || *p == '$')
+            if (*p == '$' || (*p == '^' && !after_unescaped_left_bracket))
               error (EXIT_TROUBLE, 0,
                      _("unescaped ^ or $ not supported with -Pz"));
+            escaped = *p == '\\';
+            after_unescaped_left_bracket = *p == '[';
           }
     }
 
diff --git a/tests/pcre b/tests/pcre
index b8b4662..8f3d9a4 100755
--- a/tests/pcre
+++ b/tests/pcre
@@ -15,5 +15,6 @@ fail=0
 echo | grep -P '\s*$' || fail=1
 echo | returns_ 2 grep -zP '\s$' || fail=1
 echo '.ab' | returns_ 1 grep -Pwx ab || fail=1
+echo x | grep -Pz '[^a]' || fail=1
 
 Exit $fail
-- 
2.5.5