diff options
author | Paul Pluzhnikov <ppluzhnikov@google.com> | 2015-03-06 09:13:16 -0800 |
---|---|---|
committer | Paul Pluzhnikov <ppluzhnikov@google.com> | 2015-03-06 09:13:16 -0800 |
commit | 895c30cb003857b52c1675f9078e6a799b231bcb (patch) | |
tree | 5efa6be9373ca6e1d8dafe195aa639c19060e494 /posix | |
parent | 5df56c7e3a236b39b3395e042015b541172f652b (diff) | |
download | glibc-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.c | 31 | ||||
-rw-r--r-- | posix/wordexp.c | 2 |
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; |