bkabrda / rpms / grep

Forked from rpms/grep 6 years ago
Clone
f8261a8
From 83a95bd8c8561875b948cadd417c653dbe7ef2e2 Mon Sep 17 00:00:00 2001
f8261a8
From: Yuliy Pisetsky <ypisetsky@fb.com>
f8261a8
Date: Thu, 01 Jan 2015 23:36:55 +0000
f8261a8
Subject: grep -F: fix a heap buffer (read) overrun
f8261a8
f8261a8
grep's read buffer is often filled to its full size, except when
f8261a8
reading the final buffer of a file.  In that case, the number of
f8261a8
bytes read may be far less than the size of the buffer.  However, for
f8261a8
certain unusual pattern/text combinations, grep -F would mistakenly
f8261a8
examine bytes in that uninitialized region of memory when searching
f8261a8
for a match.  With carefully chosen inputs, one can cause grep -F to
f8261a8
read beyond the end of that buffer altogether.  This problem arose via
f8261a8
commit v2.18-90-g73893ff with the introduction of a more efficient
f8261a8
heuristic using what is now the memchr_kwset function. The use of
f8261a8
that function in bmexec_trans could leave TP much larger than EP,
f8261a8
and the subsequent call to bm_delta2_search would mistakenly access
f8261a8
beyond end of the main input read buffer.
f8261a8
f8261a8
* src/kwset.c (bmexec_trans): When TP reaches or exceeds EP,
f8261a8
do not call bm_delta2_search.
f8261a8
* tests/kwset-abuse: New file.
f8261a8
* tests/Makefile.am (TESTS): Add it.
f8261a8
* THANKS.in: Update.
f8261a8
* NEWS (Bug fixes): Mention it.
f8261a8
f8261a8
Prior to this patch, this command would trigger a UMR:
f8261a8
f8261a8
  printf %0360db 0 | valgrind src/grep -F $(printf %019dXb 0)
f8261a8
f8261a8
  Use of uninitialised value of size 8
f8261a8
     at 0x4142BE: bmexec_trans (kwset.c:657)
f8261a8
     by 0x4143CA: bmexec (kwset.c:678)
f8261a8
     by 0x414973: kwsexec (kwset.c:848)
f8261a8
     by 0x414DC4: Fexecute (kwsearch.c:128)
f8261a8
     by 0x404E2E: grepbuf (grep.c:1238)
f8261a8
     by 0x4054BF: grep (grep.c:1417)
f8261a8
     by 0x405CEB: grepdesc (grep.c:1645)
f8261a8
     by 0x405EC1: grep_command_line_arg (grep.c:1692)
f8261a8
     by 0x4077D4: main (grep.c:2570)
f8261a8
f8261a8
See the accompanying test for how to trigger the heap buffer overrun.
f8261a8
f8261a8
Thanks to Nima Aghdaii for testing and finding numerous
f8261a8
ways to break early iterations of this patch.
f8261a8
---
f8261a8
--- a/THANKS.in
f8261a8
+++ b/THANKS.in
f8261a8
@@ -62,6 +62,7 @@ Michael Aichlmayr                   mikla@nx.com
f8261a8
 Miles Bader                         miles@ccs.mt.nec.co.jp
f8261a8
 Mirraz Mirraz                       mirraz1@rambler.ru
f8261a8
 Nelson H. F. Beebe                  beebe@math.utah.edu
f8261a8
+Nima Aghdaii                        naghdaii@fb.com
f8261a8
 Olaf Kirch                          okir@ns.lst.de
f8261a8
 Paul Kimoto                         kimoto@spacenet.tn.cornell.edu
f8261a8
 P├ęter Radics                        mitchnull@gmail.com
f8261a8
diff --git a/src/kwset.c b/src/kwset.c
f8261a8
index 6d21893..998dbfe 100644
f8261a8
--- a/src/kwset.c
f8261a8
+++ b/src/kwset.c
f8261a8
@@ -643,6 +643,8 @@ bmexec_trans (kwset_t kwset, char const *text, size_t size)
f8261a8
                     if (! tp)
f8261a8
                       return -1;
f8261a8
                     tp++;
f8261a8
+                    if (ep <= tp)
f8261a8
+                      break;
f8261a8
                   }
f8261a8
               }
f8261a8
           }
f8261a8
diff --git a/tests/Makefile.am b/tests/Makefile.am
f8261a8
index 217a731..2f69835 100644
f8261a8
--- a/tests/Makefile.am
f8261a8
+++ b/tests/Makefile.am
f8261a8
@@ -72,6 +72,7 @@ TESTS =						\
f8261a8
   inconsistent-range				\
f8261a8
   invalid-multibyte-infloop			\
f8261a8
   khadafy					\
f8261a8
+  kwset-abuse					\
f8261a8
   long-line-vs-2GiB-read			\
f8261a8
   match-lines					\
f8261a8
   max-count-overread				\
f8261a8
diff --git a/tests/Makefile.in b/tests/Makefile.in
f8261a8
index e40a070..9ecafe7 100644
f8261a8
--- a/tests/Makefile.in
f8261a8
+++ b/tests/Makefile.in
f8261a8
@@ -1376,6 +1376,7 @@ TESTS = \
f8261a8
   inconsistent-range				\
f8261a8
   invalid-multibyte-infloop			\
f8261a8
   khadafy					\
f8261a8
+  kwset-abuse					\
f8261a8
   long-line-vs-2GiB-read			\
f8261a8
   match-lines					\
f8261a8
   max-count-overread				\
cdb6747
@@ -2030,6 +2031,13 @@
cdb6747
 	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
cdb6747
 	--log-file $$b.log --trs-file $$b.trs \
cdb6747
 	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
cdb6747
+	"$$tst" $(AM_TESTS_FD_REDIRECT)
cdb6747
+kwset-abuse.log: kwset-abuse
cdb6747
+	@p='kwset-abuse'; \
cdb6747
+	b='kwset-abuse'; \
cdb6747
+	$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
cdb6747
+	--log-file $$b.log --trs-file $$b.trs \
cdb6747
+	$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
cdb6747
 	"$$tst" $(AM_TESTS_FD_REDIRECT)
cdb6747
 long-line-vs-2GiB-read.log: long-line-vs-2GiB-read
cdb6747
 	@p='long-line-vs-2GiB-read'; \
f8261a8
diff --git a/tests/kwset-abuse b/tests/kwset-abuse
f8261a8
new file mode 100755
f8261a8
index 0000000..6d8ec0c
f8261a8
--- a/dev/null
f8261a8
+++ b/tests/kwset-abuse
f8261a8
@@ -0,0 +1,32 @@
f8261a8
+#! /bin/sh
f8261a8
+# Evoke a segfault in a hard-to-reach code path of kwset.c.
f8261a8
+# This bug affected grep versions 2.19 through 2.21.
f8261a8
+#
f8261a8
+# Copyright (C) 2015 Free Software Foundation, Inc.
f8261a8
+#
f8261a8
+# This program is free software: you can redistribute it and/or modify
f8261a8
+# it under the terms of the GNU General Public License as published by
f8261a8
+# the Free Software Foundation, either version 3 of the License, or
f8261a8
+# (at your option) any later version.
f8261a8
+
f8261a8
+# This program is distributed in the hope that it will be useful,
f8261a8
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
f8261a8
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
f8261a8
+# GNU General Public License for more details.
f8261a8
+
f8261a8
+# You should have received a copy of the GNU General Public License
f8261a8
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
f8261a8
+
f8261a8
+. "${srcdir=.}/init.sh"; path_prepend_ ../src
f8261a8
+
f8261a8
+fail=0
f8261a8
+
f8261a8
+# This test case chooses a haystack of size 260,000, since prodding
f8261a8
+# with gdb showed a reallocation slightly larger than that in fillbuf.
f8261a8
+# To reach the buggy code, the needle must have length < 1/11 that of
f8261a8
+# the haystack, and 10,000 is a nice round number that fits the bill.
f8261a8
+printf '%0260000dXy\n' 0 | grep -F $(printf %010000dy 0)
f8261a8
+
f8261a8
+test $? = 1 || fail=1
f8261a8
+
f8261a8
+Exit $fail
f8261a8
--
f8261a8
cgit v0.9.0.2