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