Fix BZ 18036 buffer overflow (read past end of buffer) in internal_fnmatch
authorPaul Pluzhnikov <ppluzhnikov@google.com>
Mon, 2 Mar 2015 21:34:22 +0000 (13:34 -0800)
committerPaul Pluzhnikov <ppluzhnikov@google.com>
Mon, 2 Mar 2015 21:34:22 +0000 (13:34 -0800)
ChangeLog
NEWS
posix/fnmatch_loop.c
posix/tst-fnmatch3.c

index 5226f3d..98fbedb 100644 (file)
--- 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 1c54ede..8976f11 100644 (file)
--- 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
index 72c5d8f..f46c9df 100644 (file)
@@ -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;
 
index 75bc00a..fdf9934 100644 (file)
    <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 ()