Index: lib/libc/stdio/fmemopen.c =================================================================== --- lib/libc/stdio/fmemopen.c +++ lib/libc/stdio/fmemopen.c @@ -74,10 +74,9 @@ } /* - * There's no point in requiring an automatically allocated buffer - * in write-only mode. + * An automatically allocated buffer is only allowed in read-write mode. */ - if (!(flags & O_RDWR) && buf == NULL) { + if ((flags & O_ACCMODE) != O_RDWR && buf == NULL) { errno = EINVAL; return (NULL); } @@ -136,9 +135,10 @@ break; } + /* Disable read in O_WRONLY mode, and write in O_RDONLY mode */ f = funopen(ck, - flags & O_WRONLY ? NULL : fmemopen_read, - flags & O_RDONLY ? NULL : fmemopen_write, + (flags & O_ACCMODE) == O_WRONLY ? NULL : fmemopen_read, + (flags & O_ACCMODE) == O_RDONLY ? NULL : fmemopen_write, fmemopen_seek, fmemopen_close); if (f == NULL) { Index: lib/libc/tests/stdio/fmemopen2_test.c =================================================================== --- lib/libc/tests/stdio/fmemopen2_test.c +++ lib/libc/tests/stdio/fmemopen2_test.c @@ -132,9 +132,11 @@ /* Open a FILE * using a wrong mode */ fp = fmemopen(NULL, 512, "r"); ATF_REQUIRE(fp == NULL); + ATF_REQUIRE(errno == EINVAL); fp = fmemopen(NULL, 512, "w"); ATF_REQUIRE(fp == NULL); + ATF_REQUIRE(errno == EINVAL); } ATF_TC_WITHOUT_HEAD(test_data_length); @@ -271,6 +273,32 @@ ATF_REQUIRE(errno == EINVAL); } +/* PR281953 */ +ATF_TC_WITHOUT_HEAD(test_rdonly_wronly); +ATF_TC_BODY(test_rdonly_wronly, tc) +{ + FILE *fp; + char buf[16]; + char buf_orig[16] = "input data"; + char buf_write[16] = "write"; + size_t sz; + + memcpy(buf, buf_orig, sizeof(buf)); + fp = fmemopen(buf, sizeof(buf), "r"); + ATF_REQUIRE(fp != NULL); + sz = fwrite(buf_write, 1, strlen(buf_write), fp); + ATF_REQUIRE(sz == 0); + ATF_REQUIRE(errno == EBADF); + ATF_REQUIRE(memcmp(buf, buf_orig, sizeof(buf)) == 0); + fclose(fp); + + fp = fmemopen(buf_orig, sizeof(buf), "w"); + sz = fread(buf, sizeof(buf), 1, fp); + ATF_REQUIRE(sz == 0); + ATF_REQUIRE(errno == EBADF); + fclose(fp); +} + ATF_TP_ADD_TCS(tp) { @@ -280,6 +308,7 @@ ATF_TP_ADD_TC(tp, test_binary); ATF_TP_ADD_TC(tp, test_append_binary_pos); ATF_TP_ADD_TC(tp, test_size_0); + ATF_TP_ADD_TC(tp, test_rdonly_wronly); return (atf_no_error()); }