Subject: [PATCH] grep: fix crash with a pattern of alternation of two same characters

From: Norihiro Tanaka <[email-masked]>
Date: Fri, 15 Jul 2016 00:07:13 +0900

Current master crashes with below.

$ printf '0\n0' >pat
$ printf '0\n' >in
$ env LC_ALL=C grep -F pat in

grep -F uses memchr2() for each character in this pattern, but if two
characters is same, the trie has no child.
From 3b004a66cc9dc66ad62111bc38b2c5a2b8bb082c Mon Sep 17 00:00:00 2001
From: Norihiro Tanaka <[email-masked]>
Date: Thu, 14 Jul 2016 23:45:45 +0900
Subject: [PATCH] grep: fix crash with a pattern of alternation of two same characters

grep -F crashes with pattern as 0\n0.  This bug is introduced in
966f6586fbce3081ce6e5e2f9b55301b0ec3d2b4.

* src/kwset.c (memoff2_kwset): If two characters is same, memchr instead
of memchr2.
* tests/two-chars: New test.
* tests/Makefile.am (TESTS): Add it.
---
 src/kwset.c       |    7 ++++++-
 tests/Makefile.am |    1 +
 tests/two-chars   |   25 +++++++++++++++++++++++++
 3 files changed, 32 insertions(+), 1 deletions(-)
 create mode 100755 tests/two-chars

diff --git a/src/kwset.c b/src/kwset.c
index 7391990..80df752 100644
--- a/src/kwset.c
+++ b/src/kwset.c
@@ -643,8 +643,13 @@ memoff2_kwset (char const *s, size_t n, kwset_t kwset,
 {
   struct tree const *link = kwset->trie->links;
   struct tree const *clink = link->llink ? link->llink : link->rlink;
+  char const *mch;
+
+  if (clink)
+    mch = memchr2 (s, link->label, clink->label, n);
+  else
+    mch = memchr (s, link->label, n);
 
-  char const *mch = memchr2 (s, link->label, clink->label, n);
   if (! mch)
     return SIZE_MAX;
   else
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 38b0e32..b29328b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -134,6 +134,7 @@ TESTS =						\
   turkish-I					\
   turkish-I-without-dot				\
   turkish-eyes					\
+  two-chars					\
   two-files					\
   unibyte-binary				\
   unibyte-bracket-expr				\
diff --git a/tests/two-chars b/tests/two-chars
new file mode 100755
index 0000000..43a1418
--- /dev/null
+++ b/tests/two-chars
@@ -0,0 +1,25 @@
+#! /bin/sh
+# Read two files, of increasing size.
+# With ASAN, this would have triggered a false-positive read of poisoned memory.
+#
+# Copyright (C) 2014-2016 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
+
+require_en_utf8_locale_
+
+fail=0
+
+for LOC in en_US.UTF-8 $zh $LOCALE_FR_UTF8; do
+  printf '0\n0\n' >pat
+  printf '0\n' >in
+  out=out-$LOC
+  LC_ALL=$LOC grep -Ff pat in >$out || fail=1
+  compare in $out || fail=1
+done
+
+Exit $fail
-- 
1.7.1