On 2026-06-16 14:47, kalfalakh wrote:
GNU tar extracting a member "a/./b" fails with ENOENT.
It is due to a bug in the emulation of openat2(), more
specifically when processing dotlike components,
resulting in openat() being called on "". Please see
the proposed attached patch.
Thanks for reporting the problem. I think I see the cause, and installed
the attached patch into Gnulib. Please give the patch a try. If it
doesn't fix things for you, please let us know the platform you're
running on. Also, it'd be nice to see a test case illustrating the
unfixed bug, e.g., in the form of a patch to tests/test-openat2.c.From 50d7bb88f547aff37e6279bdc84a7602e1dd3533 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Wed, 17 Jun 2026 00:19:35 -0700
Subject: [PATCH] openat2: fix bug with trailing "/./"
Problem reported by Kinan Al-Falakh in:
https://lists.gnu.org/r/bug-gnulib/2026-06/msg00070.html
* lib/openat2.c (do_openat2): When opening a dotlike component at
file name end, also set the G and H indexes appropriately for ".".
This matters if the file name ends in something like "/./" so the
last component "." is not at file name end.
* tests/test-openat2.c (do_test_resolve): Test for the bug.
---
ChangeLog | 11 +++++++++++
lib/openat2.c | 3 ++-
tests/test-openat2.c | 11 +++++++++++
3 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/ChangeLog b/ChangeLog
index ee4fcf6978..845f806fc6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2026-06-17 Paul Eggert <[email protected]>
+
+ openat2: fix bug with trailing "/./"
+ Problem reported by Kinan Al-Falakh in:
+ https://lists.gnu.org/r/bug-gnulib/2026-06/msg00070.html
+ * lib/openat2.c (do_openat2): When opening a dotlike component at
+ file name end, also set the G and H indexes appropriately for ".".
+ This matters if the file name ends in something like "/./" so the
+ last component "." is not at file name end.
+ * tests/test-openat2.c (do_test_resolve): Test for the bug.
+
2026-06-16 Paul Eggert <[email protected]>
openat2: set HAVE_OPENAT2=0 if openat2 is missing
diff --git a/lib/openat2.c b/lib/openat2.c
index 2be62c921c..8c722427f7 100644
--- a/lib/openat2.c
+++ b/lib/openat2.c
@@ -320,8 +320,9 @@ do_openat2 (int *fd, char const *filename,
{
/* This is empty or the last component, and acts like ".".
Use "." regardless of whether it was "" or "." or "..". */
- f = sizeof ".";
+ f = g = sizeof ".";
e[-f] = '.';
+ h = 1;
}
/* Open the current component, as either an internal directory or
diff --git a/tests/test-openat2.c b/tests/test-openat2.c
index 0085410ed9..cde9576fbd 100644
--- a/tests/test-openat2.c
+++ b/tests/test-openat2.c
@@ -514,6 +514,17 @@ do_test_resolve (void)
ASSERT (errno == EXDEV);
ASSERT (fd == -1);
+ /* Check that RESOLVE_BENEATH works with trailing "/./". */
+ fd = openat2 (dfd,
+ "subdir/./",
+ (&(struct open_how)
+ {
+ .flags = O_RDONLY,
+ .resolve = RESOLVE_BENEATH,
+ }),
+ sizeof (struct open_how));
+ ASSERT (close (fd) == 0);
+
ASSERT (close (subdfd) == 0);
}
}
--
2.53.0