summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNorihiro Tanaka <noritnk@kcn.ne.jp>2017-01-21 18:01:53 +0900
committerJim Meyering <meyering@fb.com>2017-01-21 08:03:20 -0800
commitb0cdf48d416b2cbb028a1b65c758035ba7c8a2aa (patch)
tree57f19acee0c29603f5ede6e1665d60b4aed5c850
parentb408bcee1e81a2c4cc187d520b1fd5ae0da68f13 (diff)
downloadgrep-b0cdf48d416b2cbb028a1b65c758035ba7c8a2aa.tar.gz
grep -Fo could report a match that is not the longest
* src/kwset.c (acexec): Fix it. * tests/fgrep-longest: New test. * tests/Makefile.am: Add the test. * NEWS: Mention it.
-rw-r--r--NEWS4
-rw-r--r--src/kwset.c17
-rwxr-xr-xtests/fgrep-longest23
3 files changed, 41 insertions, 3 deletions
diff --git a/NEWS b/NEWS
index 3529f4e6..773a8ed1 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,10 @@ GNU grep NEWS -*- outline -*-
** Bug fixes
+ When grep -Fo finds matches of differing length, it could
+ mistakenly print a shorter one. Now it prints a longest one.
+ [bug introduced in grep-2.26]
+
When standard output is /dev/null, grep no longer fails when
standard input is a file in the Linux /proc file system, or when
standard input is a pipe and standard output is in append mode.
diff --git a/src/kwset.c b/src/kwset.c
index 39a1e157..258cff53 100644
--- a/src/kwset.c
+++ b/src/kwset.c
@@ -848,9 +848,20 @@ acexec_trans (kwset_t kwset, char const *text, ptrdiff_t len,
struct trie const *accept1;
char const *left1;
unsigned char c = tr (trans, *tp++);
- tree = trie->links;
- while (tree && c != tree->label)
- tree = c < tree->label ? tree->llink : tree->rlink;
+ while (true)
+ {
+ tree = trie->links;
+ while (tree && c != tree->label)
+ tree = c < tree->label ? tree->llink : tree->rlink;
+ if (tree)
+ break;
+ trie = trie->fail;
+ if (!trie)
+ break;
+ left1 = tp - trie->depth;
+ if (left1 > left)
+ break;
+ }
if (!tree)
break;
trie = tree->trie;
diff --git a/tests/fgrep-longest b/tests/fgrep-longest
new file mode 100755
index 00000000..5974d113
--- /dev/null
+++ b/tests/fgrep-longest
@@ -0,0 +1,23 @@
+#! /bin/sh
+# With multiple matches, grep -Fo could print a shorter one.
+# This bug affected grep versions 2.26 through 2.27.
+#
+# Copyright (C) 2017 Free Software Foundation, Inc.
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+
+. "${srcdir=.}/init.sh"; path_prepend_ ../src
+
+fail=0
+
+# The erroneous versions would print "c", rather than the longer match, "bce".
+printf 'abce\n' > in || framework_failure_
+printf 'abcd\nc\nbce\n' > pat || framework_failure_
+printf 'bce\n' > exp || framework_failure_
+
+LC_ALL=C grep -Fof pat in > out || fail=1
+compare exp out || fail=1
+
+Exit $fail