Paul Eggert wrote:
> > 2) On FreeBSD 14.0 and NetBSD 10.0:
> 
> I installed the first attached patch to fix that. Tested on cfarm240, 
> which is FreeBSD 15.0-CURRENT.

Thanks. I confirm this fixes the failure on FreeBSD and NetBSD.

> > 1) On Cygwin 3.x:
> 
> Although I don't have easy access to that platform I looked at its 
> source code and see what may be the issue: its O_TMPFILE is a single bit 
> whereas GNU/Linux's is a hacky combination that includes O_DIRECTORY. I 
> installed the 2nd attached patch to try to fix that issue. This may not 
> suffice for Cygwin but the patch needed to be done anyway.

The test failure is still there. What happens that

  1. In do_openat2, at the line
       while (1 < h && !ISSLASH (e[- --h]))
     h gets decremented twice, because ISSLASH evaluates its argument
     multiple times,

  2. In do_openat2, at the line
       e[-h] = '\0';
     h is 0, thus this stores a NUL byte outside the given stackbuf,

  3. In the caller, the value of *buf, that was 0xffffc8b0, has been
     changed to 0xffffc800, and thus the code
       if (buf != stackbuf)
         free (buf);
     frees a pointer that was never malloc()ed.

A beautiful bug :)

> > 3) On MSVC (but not on mingw):
> >...
> > I think I can deal with 3), but I'll let you deal with 1) and 2) first.

Also fixed through the patches below.


2025-11-01  Bruno Haible  <[email protected]>

        openat2 tests: Avoid test failure on native Windows.
        * tests/test-openat2.c (do_prepare_symlinks): New function, extracted
        from do_prepare.
        (main): Invoke it before do_test_resolve, do_test_basic. Disable these
        tests on native Windows.

2025-11-01  Bruno Haible  <[email protected]>

        openat2: Fix invalid memory access on Cygwin.
        * lib/openat2.c (do_openat2): Don't use an expression with side effects
        as argument of ISSLASH.

2025-11-01  Bruno Haible  <[email protected]>

        openat2 tests: Avoid gratuitous test failure when debugging.
        * tests/test-openat2.c: Include ignore-value.h.
        (do_prepare): Remove left-overs on disk.
        * modules/openat2-tests (Depends-on): Add ignore-value.


>From 5746cd1cdbb2caf0e321ea79041885fc7ef22423 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 1 Nov 2025 12:47:38 +0100
Subject: [PATCH 1/3] openat2 tests: Avoid gratuitous test failure when
 debugging.

* tests/test-openat2.c: Include ignore-value.h.
(do_prepare): Remove left-overs on disk.
* modules/openat2-tests (Depends-on): Add ignore-value.
---
 ChangeLog             | 7 +++++++
 modules/openat2-tests | 1 +
 tests/test-openat2.c  | 4 ++++
 3 files changed, 12 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index c02c1c14b9..8d0aa9f023 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2025-11-01  Bruno Haible  <[email protected]>
+
+	openat2 tests: Avoid gratuitous test failure when debugging.
+	* tests/test-openat2.c: Include ignore-value.h.
+	(do_prepare): Remove left-overs on disk.
+	* modules/openat2-tests (Depends-on): Add ignore-value.
+
 2025-11-01  Bruno Haible  <[email protected]>
 
 	fprintftime: Return -1 on output error.
diff --git a/modules/openat2-tests b/modules/openat2-tests
index 88126f60ad..25a0ea2edb 100644
--- a/modules/openat2-tests
+++ b/modules/openat2-tests
@@ -7,6 +7,7 @@ tests/macros.h
 Depends-on:
 close
 fcntl
+ignore-value
 mkdirat
 stdcountof-h
 stdint-h
diff --git a/tests/test-openat2.c b/tests/test-openat2.c
index fc93a7a9a9..a3832992ec 100644
--- a/tests/test-openat2.c
+++ b/tests/test-openat2.c
@@ -36,6 +36,7 @@ SIGNATURE_CHECK (openat2, int, (int, char const *,
 # include <signal.h>
 #endif
 
+#include "ignore-value.h"
 #include "macros.h"
 
 #define BASE "test-openat2.t"
@@ -71,6 +72,9 @@ do_open (char const *name, int flags, ...)
 static void
 do_prepare ()
 {
+  /* Remove any leftovers from a previous partial run.  */
+  ignore_value (system ("rm -rf " BASE "*"));
+
   /*
      Construct a test directory with the following structure:
 
-- 
2.51.0

>From 3d23c8df2582a6b0e44e048d431ecb00a14667ec Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 1 Nov 2025 13:37:35 +0100
Subject: [PATCH 2/3] openat2: Fix invalid memory access on Cygwin.

* lib/openat2.c (do_openat2): Don't use an expression with side effects
as argument of ISSLASH.
---
 ChangeLog     | 6 ++++++
 lib/openat2.c | 8 ++++++--
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 8d0aa9f023..116b967c54 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2025-11-01  Bruno Haible  <[email protected]>
+
+	openat2: Fix invalid memory access on Cygwin.
+	* lib/openat2.c (do_openat2): Don't use an expression with side effects
+	as argument of ISSLASH.
+
 2025-11-01  Bruno Haible  <[email protected]>
 
 	openat2 tests: Avoid gratuitous test failure when debugging.
diff --git a/lib/openat2.c b/lib/openat2.c
index ee64d05836..4ad4e88f6c 100644
--- a/lib/openat2.c
+++ b/lib/openat2.c
@@ -267,8 +267,12 @@ do_openat2 (int *fd, char const *filename,
             }
         }
       idx_t h = g;
-      while (1 < h && !ISSLASH (e[- --h]))
-        continue;
+      while (h > 1)
+        {
+          h--;
+          if (ISSLASH (e[-h]))
+            break;
+        }
 
       /* Properties of the file name through the first component's end,
          or to file name end if there is no component.  */
-- 
2.51.0

>From a209366ed34eca8ede481ec1b1c4e22f614c448d Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Sat, 1 Nov 2025 14:17:10 +0100
Subject: [PATCH 3/3] openat2 tests: Avoid test failure on native Windows.

* tests/test-openat2.c (do_prepare_symlinks): New function, extracted
from do_prepare.
(main): Invoke it before do_test_resolve, do_test_basic. Disable these
tests on native Windows.
---
 ChangeLog            |  8 ++++++++
 tests/test-openat2.c | 23 ++++++++++++++++-------
 2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 116b967c54..bf7345152d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2025-11-01  Bruno Haible  <[email protected]>
+
+	openat2 tests: Avoid test failure on native Windows.
+	* tests/test-openat2.c (do_prepare_symlinks): New function, extracted
+	from do_prepare.
+	(main): Invoke it before do_test_resolve, do_test_basic. Disable these
+	tests on native Windows.
+
 2025-11-01  Bruno Haible  <[email protected]>
 
 	openat2: Fix invalid memory access on Cygwin.
diff --git a/tests/test-openat2.c b/tests/test-openat2.c
index a3832992ec..e22c461c7c 100644
--- a/tests/test-openat2.c
+++ b/tests/test-openat2.c
@@ -75,11 +75,21 @@ do_prepare ()
   /* Remove any leftovers from a previous partial run.  */
   ignore_value (system ("rm -rf " BASE "*"));
 
+  ASSERT (mkdirat (AT_FDCWD, temp_dir, 0700) == 0);
+  dfd = openat2 (AT_FDCWD, temp_dir,
+                 (&(struct open_how) { .flags = O_RDONLY | O_DIRECTORY }),
+                 sizeof (struct open_how));
+  ASSERT (0 <= dfd);
+}
+
+static void
+do_prepare_symlinks ()
+{
   /*
      Construct a test directory with the following structure:
 
      temp_dir/
-        |- escaping_link -> /tmp
+        |- escaping_link -> /
         |- escaping_link_2 -> escaping_link
         |- some_file
         |- invalid_link -> some_file/invalid
@@ -88,11 +98,6 @@ do_prepare ()
 	   |- some_file
   */
 
-  ASSERT (mkdirat (AT_FDCWD, temp_dir, 0700) == 0);
-  dfd = openat2 (AT_FDCWD, temp_dir,
-                 (&(struct open_how) { .flags = O_RDONLY | O_DIRECTORY }),
-                 sizeof (struct open_how));
-  ASSERT (0 <= dfd);
   ASSERT (symlinkat ("/", dfd, "escaping_link") == 0);
   ASSERT (symlinkat ("escaping_link", dfd, "escaping_link_2") == 0);
   ASSERT (symlinkat ("some_file/invalid", dfd, "invalid_link") == 0);
@@ -522,11 +527,15 @@ main ()
   ASSERT (test_open (do_open, false) == result);
   ASSERT (close (dfd) == 0);
 
-  do_prepare ();
   do_test_struct ();
+
+  do_prepare ();
   do_test_flags ();
+#if !(defined _WIN32 && !defined __CYGWIN__)
+  do_prepare_symlinks ();
   do_test_resolve ();
   do_test_basic ();
+#endif
 
   /* Check that even when *-safer modules are in use, plain openat2 can
      land in fd 0.  Do this test last, since it is destructive to
-- 
2.51.0

Reply via email to