summary refs log tree commit diff
path: root/posix
diff options
context:
space:
mode:
authorPaul Pluzhnikov <ppluzhnikov@google.com>2015-03-06 09:13:16 -0800
committerPaul Pluzhnikov <ppluzhnikov@google.com>2015-03-06 09:13:16 -0800
commit895c30cb003857b52c1675f9078e6a799b231bcb (patch)
tree5efa6be9373ca6e1d8dafe195aa639c19060e494 /posix
parent5df56c7e3a236b39b3395e042015b541172f652b (diff)
downloadglibc-895c30cb003857b52c1675f9078e6a799b231bcb.tar.gz
glibc-895c30cb003857b52c1675f9078e6a799b231bcb.tar.xz
glibc-895c30cb003857b52c1675f9078e6a799b231bcb.zip
Fix BZ #18043: buffer-overflow (read past the end) in wordexp/parse_dollars/parse_param
Diffstat (limited to 'posix')
-rw-r--r--posix/wordexp-test.c31
-rw-r--r--posix/wordexp.c2
2 files changed, 32 insertions, 1 deletions
diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c
index 8a312e0bcd..137044e95f 100644
--- a/posix/wordexp-test.c
+++ b/posix/wordexp-test.c
@@ -17,6 +17,7 @@
 
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/mman.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <pwd.h>
@@ -249,6 +250,33 @@ command_line_test (const char *words)
     printf ("we_wordv[%d] = \"%s\"\n", i, we.we_wordv[i]);
 }
 
+static int
+do_bz18043 (void)
+{
+  const int pagesize = getpagesize ();
+  char *start = mmap (0, 2 * pagesize, PROT_READ|PROT_WRITE,
+		      MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+
+  if (start == MAP_FAILED)
+    return 1;
+
+  if (mprotect (start + pagesize, pagesize, PROT_NONE))
+    return 2;
+
+  const char word[] = "${";
+  char *word_start = start + pagesize - sizeof (word);
+  memcpy (word_start, word, sizeof (word));
+
+  wordexp_t w;
+  if (wordexp (word_start, &w, 0) != WRDE_SYNTAX)
+    return 3;
+
+  if (munmap (start, 2 * pagesize) != 0)
+    return 4;
+
+  return 0;
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -370,6 +398,9 @@ main (int argc, char *argv[])
 
   printf ("tests failed: %d\n", fail);
 
+  if (do_bz18043 ())
+    ++fail;
+
   return fail != 0;
 }
 
diff --git a/posix/wordexp.c b/posix/wordexp.c
index e3d8d6bd0d..1c144014b3 100644
--- a/posix/wordexp.c
+++ b/posix/wordexp.c
@@ -1299,7 +1299,7 @@ parse_param (char **word, size_t *word_length, size_t *max_length,
 	}
       while (isdigit(words[++*offset]));
     }
-  else if (strchr ("*@$", words[*offset]) != NULL)
+  else if (words[*offset] != '\0' && strchr ("*@$", words[*offset]) != NULL)
     {
       /* Special parameter. */
       special = 1;