about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaul Pluzhnikov <ppluzhnikov@google.com>2015-03-02 13:34:22 -0800
committerPaul Pluzhnikov <ppluzhnikov@google.com>2015-03-02 13:34:22 -0800
commitc2c6d39fab901c97c18fa3a3a3658d9dc3f7df61 (patch)
tree43cf2e4e4f302d8bf0a841d8e06ab510b4e4aea7
parente8b6be0016f131c2ac72bf3213eabdb59800e63b (diff)
downloadglibc-c2c6d39fab901c97c18fa3a3a3658d9dc3f7df61.tar.gz
glibc-c2c6d39fab901c97c18fa3a3a3658d9dc3f7df61.tar.xz
glibc-c2c6d39fab901c97c18fa3a3a3658d9dc3f7df61.zip
Fix BZ 18036 buffer overflow (read past end of buffer) in internal_fnmatch
-rw-r--r--ChangeLog6
-rw-r--r--NEWS4
-rw-r--r--posix/fnmatch_loop.c7
-rw-r--r--posix/tst-fnmatch3.c22
4 files changed, 35 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 5226f3decb..98fbedb4f7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2015-03-02  Paul Pluzhnikov  <ppluzhnikov@google.com>
+
+	[BZ #18036]
+	* posix/fnmatch_loop.c (END): Detect invalid pattern.
+	* posix/tst-fnmatch3.c (do_bz18036): Add test case.
+
 2015-03-02  Andreas Schwab  <schwab@suse.de>
 
 	* elf/Makefile ($(elf-objpfx)runtime-linker.st): Fix typo in
diff --git a/NEWS b/NEWS
index 1c54ede4a1..8976f1100d 100644
--- a/NEWS
+++ b/NEWS
@@ -12,8 +12,8 @@ Version 2.22
   4719, 14841, 13064, 14094, 15319, 15467, 15790, 15969, 16351, 16560,
   16783, 17269, 17523, 17569, 17588, 17711, 17792, 17836, 17912, 17916,
   17932, 17944, 17949, 17964, 17965, 17967, 17969, 17978, 17987, 17991,
-  17996, 17998, 17999, 18019, 18020, 18029, 18030, 18032, 18038, 18039,
-  18046, 18047.
+  17996, 17998, 17999, 18019, 18020, 18029, 18030, 18032, 18036, 18038,
+  18039, 18046, 18047.
 
 * Character encoding and ctype tables were updated to Unicode 7.0.0, using
   new generator scripts contributed by Pravin Satpute and Mike FABIAN (Red
diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c
index 72c5d8f041..f46c9dfedb 100644
--- a/posix/fnmatch_loop.c
+++ b/posix/fnmatch_loop.c
@@ -1036,7 +1036,12 @@ END (const CHAR *pattern)
       }
     else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@')
 	      || *p == L('!')) && p[1] == L('('))
-      p = END (p + 1);
+      {
+	p = END (p + 1);
+	if (*p == L('\0'))
+	  /* This is an invalid pattern.  */
+	  return pattern;
+      }
     else if (*p == L(')'))
       break;
 
diff --git a/posix/tst-fnmatch3.c b/posix/tst-fnmatch3.c
index 75bc00a2c5..fdf99342e9 100644
--- a/posix/tst-fnmatch3.c
+++ b/posix/tst-fnmatch3.c
@@ -17,6 +17,26 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <fnmatch.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <unistd.h>
+
+int
+do_bz18036 (void)
+{
+  const char p[] = "**(!()";
+  const int pagesize = getpagesize ();
+
+  char *pattern = mmap (0, 2 * pagesize, PROT_READ|PROT_WRITE,
+                        MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+  if (pattern == MAP_FAILED) return 1;
+
+  mprotect (pattern + pagesize, pagesize, PROT_NONE);
+  memset (pattern, ' ', pagesize);
+  strcpy (pattern, p);
+
+  return fnmatch (pattern, p, FNM_EXTMATCH);
+}
 
 int
 do_test (void)
@@ -25,7 +45,7 @@ do_test (void)
     return 1;
   if (fnmatch ("[a[.\0.]]", "a", 0) != FNM_NOMATCH)
     return 1;
-  return 0;
+  return do_bz18036 ();
 }
 
 #define TEST_FUNCTION do_test ()