Subject: Re: bug#19028: [PATCH] grep: fix grep -F -x -o outputs extra newlines

From: Norihiro Tanaka <[email-masked]>
Date: Thu, 13 Nov 2014 21:50:18 +0900

On Wed, 12 Nov 2014 16:38:42 -0800
Jim Meyering <[email-masked]> wrote:
> Would you please amend it to include the test you added?

Sorry, I amend it after `git add'.
From 03495c5afb819bf289987be15c06b50c21962da7 Mon Sep 17 00:00:00 2001
From: Norihiro Tanaka <[email-masked]>
Date: Wed, 12 Nov 2014 22:25:18 +0900
Subject: [PATCH] grep: fix grep -F -x -o outputs extra newlines

* src/kwsearch.c: grep: Fix grep -F -x -o outputs extra newlines.
* tests/match-lines: Add a new test.
---
 NEWS              |  3 +++
 src/kwsearch.c    |  7 +++++--
 tests/match-lines | 38 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+), 2 deletions(-)
 create mode 100755 tests/match-lines

diff --git a/NEWS b/NEWS
index c465162..663b422 100644
--- a/NEWS
+++ b/NEWS
@@ -41,6 +41,9 @@ GNU grep NEWS                                    -*- outline -*-
   implying that the match, "10" was on line 1.
   [bug introduced in grep-2.19]
 
+  grep -F -x -o no longer output extra newline.
+  [bug introduced in grep-2.19]
+
   grep in a non-UTF8 multibyte locale could mistakenly match in the middle
   of a multibyte character when using a '^'-anchored alternate in a pattern,
   leading it to print non-matching lines.  [bug present since "the beginning"]
diff --git a/src/kwsearch.c b/src/kwsearch.c
index 6bd516a..aa965f6 100644
--- a/src/kwsearch.c
+++ b/src/kwsearch.c
@@ -129,7 +129,7 @@ Fexecute (char const *buf, size_t size, size_t *match_size,
                                buf + size - beg + match_lines, &kwsmatch);
       if (offset == (size_t) -1)
         goto failure;
-      len = kwsmatch.size[0] - match_lines;
+      len = kwsmatch.size[0] - 2 * match_lines;
       if (!match_lines && MB_CUR_MAX > 1 && !using_utf8 ()
           && mb_goback (&mb_start, beg + offset, buf + size) != 0)
         {
@@ -142,7 +142,10 @@ Fexecute (char const *buf, size_t size, size_t *match_size,
       if (start_ptr && !match_words)
         goto success_in_beg_and_len;
       if (match_lines)
-        goto success_in_beg_and_len;
+        {
+          len += start_ptr == NULL;
+          goto success_in_beg_and_len;
+        }
       if (match_words)
         for (try = beg; ; )
           {
diff --git a/tests/match-lines b/tests/match-lines
new file mode 100755
index 0000000..3c90443
--- /dev/null
+++ b/tests/match-lines
@@ -0,0 +1,38 @@
+#!/bin/sh
+# Trigger a bug in the DFA matcher.
+# This would fail for grep-2.20.
+
+# Copyright 2014 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../src
+
+printf 'a\n' > in || framework_failure_
+
+fail=0
+
+for locale in C en_US.UTF-8; do
+  for options in -x '-E -x' '-F -x'; do
+    LC_ALL=$locale grep $options a in > out || fail=1
+    compare out in || fail=1
+  done
+
+  for options in '-x -o' '-E -x -o' '-F -x -o'; do
+    LC_ALL=$locale grep $options a in > out
+    compare out in || fail=1
+  done
+done
+
+Exit $fail
-- 
2.1.3