On 3/4/20 9:24 AM, Dan Gohman wrote:
Would
    if (flags & ((O_CREAT | O_WRONLY | O_RDWR) & ~O_RDONLY))
be correct?

That would fix the problem for systems that define O_RDONLY as Hurd does,
while not breaking any known systems.

It wouldn't be correct on a hypothetical system

Thanks for mentioning this. We might as well fix the code for the hypothetical systems while we're at it, since we can use O_ACCMODE here. The issue also occurs in the 'open' wrapper. I installed the attached patch.
>From 1d86584739a712597a6fe3a62ec412238f0f13f8 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Sat, 7 Mar 2020 11:02:05 -0800
Subject: [PATCH] open, openat: port to (O_RDWR | O_RDONLY) != 0
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Potential portability problem reported by Dan Gohman in:
https://lists.gnu.org/r/bug-gnulib/2020-03/msg00000.html
* lib/open.c (open):
* lib/openat.c (rpl_openat):
Don’t assume O_RDONLY is disjoint from O_RDWR.
---
 ChangeLog    | 9 +++++++++
 lib/open.c   | 4 +++-
 lib/openat.c | 4 +++-
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 0eddfee99..f6bd5180c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2020-03-07  Paul Eggert  <[email protected]>
+
+	open, openat: port to (O_RDWR | O_RDONLY) != 0
+	Potential portability problem reported by Dan Gohman in:
+	https://lists.gnu.org/r/bug-gnulib/2020-03/msg00000.html
+	* lib/open.c (open):
+	* lib/openat.c (rpl_openat):
+	Don’t assume O_RDONLY is disjoint from O_RDWR.
+
 2020-03-07  Bruno Haible  <[email protected]>
 
 	findprog, relocatable-prog: Ignore directories during PATH search.
diff --git a/lib/open.c b/lib/open.c
index 487194f66..bb180fde2 100644
--- a/lib/open.c
+++ b/lib/open.c
@@ -110,7 +110,9 @@ open (const char *filename, int flags, ...)
          directories,
        - if O_WRONLY or O_RDWR is specified, open() must fail because the
          file does not contain a '.' directory.  */
-  if (flags & (O_CREAT | O_WRONLY | O_RDWR))
+  if ((flags & O_CREAT)
+      || (flags & O_ACCMODE) == O_RDWR
+      || (flags & O_ACCMODE) == O_WRONLY)
     {
       size_t len = strlen (filename);
       if (len > 0 && filename[len - 1] == '/')
diff --git a/lib/openat.c b/lib/openat.c
index 7d67dc4ca..fdbe83f43 100644
--- a/lib/openat.c
+++ b/lib/openat.c
@@ -100,7 +100,9 @@ rpl_openat (int dfd, char const *filename, int flags, ...)
          directories,
        - if O_WRONLY or O_RDWR is specified, open() must fail because the
          file does not contain a '.' directory.  */
-  if (flags & (O_CREAT | O_WRONLY | (O_RDWR & ~O_RDONLY)))
+  if ((flags & O_CREAT)
+      || (flags & O_ACCMODE) == O_RDWR
+      || (flags & O_ACCMODE) == O_WRONLY)
     {
       size_t len = strlen (filename);
       if (len > 0 && filename[len - 1] == '/')
-- 
2.17.1

Reply via email to