aboutsummaryrefslogtreecommitdiff
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.zip
glibc-895c30cb003857b52c1675f9078e6a799b231bcb.tar.gz
glibc-895c30cb003857b52c1675f9078e6a799b231bcb.tar.bz2
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 8a312e0..137044e 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 e3d8d6b..1c14401 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;