@@ -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;
@@ -24,6 +24,68 @@ static char buffer[] = "foobar";
#include <errno.h>
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 ()