git: 0953460ce149 - main - libc: fix access mode tests in fmemopen(3)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 23 Oct 2024 17:11:21 UTC
The branch main has been updated by emaste:
URL: https://cgit.FreeBSD.org/src/commit/?id=0953460ce149e6f384aafbcb1e6213dfbf8f6a16
commit 0953460ce149e6f384aafbcb1e6213dfbf8f6a16
Author: Ed Maste <emaste@FreeBSD.org>
AuthorDate: 2024-10-23 13:41:51 +0000
Commit: Ed Maste <emaste@FreeBSD.org>
CommitDate: 2024-10-23 17:11:14 +0000
libc: fix access mode tests in fmemopen(3)
Previously a stream opened as read-only could be written to. Add a test
case for the fix.
Also correct another incorrect access mode check that worked by
accident, and improve the tests for that.
PR: 281953
Reported by: Erkki Moorits, fuz
Reviewed by: fuz, khng (earlier)
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D47265
---
lib/libc/stdio/fmemopen.c | 10 +++++-----
lib/libc/tests/stdio/fmemopen2_test.c | 32 ++++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+), 5 deletions(-)
diff --git a/lib/libc/stdio/fmemopen.c b/lib/libc/stdio/fmemopen.c
index 2f835a34951b..dc323921d93a 100644
--- a/lib/libc/stdio/fmemopen.c
+++ b/lib/libc/stdio/fmemopen.c
@@ -74,10 +74,9 @@ fmemopen(void * __restrict buf, size_t size, const char * __restrict mode)
}
/*
- * 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 @@ fmemopen(void * __restrict buf, size_t size, const char * __restrict mode)
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) {
diff --git a/lib/libc/tests/stdio/fmemopen2_test.c b/lib/libc/tests/stdio/fmemopen2_test.c
index 2e1b9ea917a5..4a7242ee6b2f 100644
--- a/lib/libc/tests/stdio/fmemopen2_test.c
+++ b/lib/libc/tests/stdio/fmemopen2_test.c
@@ -132,9 +132,11 @@ ATF_TC_BODY(test_autoalloc, tc)
/* 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,35 @@ ATF_TC_BODY(test_size_0, tc)
ATF_REQUIRE(errno == EINVAL);
}
+/*
+ * PR281953 - ensure we cannot write in read-only only mode, and cannot read in
+ * write-only mode.
+ */
+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 +311,7 @@ ATF_TP_ADD_TCS(tp)
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());
}