diff --git a/libio/fmemopen.c b/libio/fmemopen.c index 3ab3e8d..2cf45c0 100644 --- a/libio/fmemopen.c +++ b/libio/fmemopen.c @@ -144,12 +144,30 @@ fmemopen_close (void *cookie) } +/* Check valid open mode. Only "(r|w|a)\+?" are valid. */ +static int +valid_mode_p (const char *mode) +{ + if (mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') + return 0; + if (mode[1] == '\0' || (mode[1] == '+' && mode[2] == '\0')) + return 1; + + return 0; +} + FILE * __fmemopen (void *buf, size_t len, const char *mode) { cookie_io_functions_t iof; fmemopen_cookie_t *c; + if (!valid_mode_p (mode)) + { + __set_errno (EINVAL); + return NULL; + } + c = (fmemopen_cookie_t *) calloc (sizeof (fmemopen_cookie_t), 1); if (c == NULL) return NULL; diff --git a/libio/test-fmemopen.c b/libio/test-fmemopen.c index 63ca89f..7c6b4e5 100644 --- a/libio/test-fmemopen.c +++ b/libio/test-fmemopen.c @@ -24,6 +24,68 @@ static char buffer[] = "foobar"; #include static int +do_bz18757_one (const char *mode) +{ + char c = 0; + FILE *stream; + + errno = 0; + stream = fmemopen (&c, 1, mode); + if (stream == NULL) + { + if (errno == EINVAL) + return 1; + + printf ("fmemopen invalid mode %s: %m\n", mode); + return 2; + } + + fclose (stream); + return 0; +} + +static int +do_bz18757 (void) +{ + int ret = 0; + int j, k; + const char valid[] = "rwa"; + const char invalid[][4] = {"?", "rw", "r++", "+w", "a+r"}; + + /* Test all valid modes. */ + for (j = 0; j < strlen(valid); ++j) + for (k = 0; k < 2; ++k) + { + char mode[3]; + + mode[0] = valid[j]; + mode[1] = k ? '\0' : '+'; + mode[2] = '\0'; + + if (do_bz18757_one (mode)) + { + printf ("fmemopen rejected '%s'\n", mode); + ret += 1; + } + } + + /* Test some invalid modes. */ + for (j = 0; j < sizeof (invalid) / sizeof (invalid[0][0]); ++j) + { + const char *mode = invalid[j]; + int rc = do_bz18757_one (mode); + + if (rc != 1) + { + printf ("mode: %s, expected 1, got %d\n", mode, rc); + ret += 1; + } + } + + return ret; +} + +static int do_test (void) { int ch; @@ -44,7 +106,7 @@ do_test (void) fclose (stream); - return ret; + return ret + do_bz18757 (); } #define TEST_FUNCTION do_test ()