git: 90c5d1b5f423 - stable/14 - scandir: Fix behavior when no entries match.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 05 Feb 2026 15:27:22 UTC
The branch stable/14 has been updated by des:
URL: https://cgit.FreeBSD.org/src/commit/?id=90c5d1b5f4238823414a82b72e7f80d9e83a3de6
commit 90c5d1b5f4238823414a82b72e7f80d9e83a3de6
Author: Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2025-06-20 16:13:48 +0000
Commit: Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2026-02-05 14:47:46 +0000
scandir: Fix behavior when no entries match.
In the previous commit, I removed the initial initialization of the
`names` array, not realizing that `scandir()` is expected to return
a non-null (but empty) array of entries if no entries matched.
Restore the historical behavior, document it, and add a test.
Fixes: deeebfdecab5
Sponsored by: Klara, Inc.
Reviewed by: kevans, allanjude, markj
Differential Revision: https://reviews.freebsd.org/D50949
(cherry picked from commit c187b673bb79905b5d5db1eb34d5a893c4464eeb)
---
lib/libc/gen/scandir.3 | 5 +++--
lib/libc/gen/scandir.c | 6 +++++-
lib/libc/tests/gen/scandir_test.c | 22 ++++++++++++++++++++++
3 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/lib/libc/gen/scandir.3 b/lib/libc/gen/scandir.3
index d9ae8f687168..c55c69eeca24 100644
--- a/lib/libc/gen/scandir.3
+++ b/lib/libc/gen/scandir.3
@@ -27,7 +27,7 @@
.\"
.\" @(#)scandir.3 8.1 (Berkeley) 6/4/93
.\"
-.Dd June 19, 2025
+.Dd June 20, 2025
.Dt SCANDIR 3
.Os
.Sh NAME
@@ -104,7 +104,8 @@ entries using
It returns the number of entries in the array.
A pointer to the array of directory entries is stored in the location
referenced by
-.Fa namelist .
+.Fa namelist
+(even if no entries were selected).
.Pp
The
.Fa select
diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c
index 54f92bafc115..36abe9f37047 100644
--- a/lib/libc/gen/scandir.c
+++ b/lib/libc/gen/scandir.c
@@ -76,9 +76,13 @@ scandir_dirp(DIR *dirp, struct dirent ***namelist,
#endif
{
struct dirent *d, *p = NULL, **names = NULL, **names2;
- size_t arraysz = 0, numitems = 0;
+ size_t arraysz = 32, numitems = 0;
int serrno;
+ names = malloc(arraysz * sizeof(*names));
+ if (names == NULL)
+ return (-1);
+
while ((d = readdir(dirp)) != NULL) {
if (select != NULL && !SELECT(d))
continue; /* just selected names */
diff --git a/lib/libc/tests/gen/scandir_test.c b/lib/libc/tests/gen/scandir_test.c
index 54848c0572ca..dcd73fe94df5 100644
--- a/lib/libc/tests/gen/scandir_test.c
+++ b/lib/libc/tests/gen/scandir_test.c
@@ -103,10 +103,32 @@ ATF_TC_BODY(scandirat_test, tc)
ATF_REQUIRE_EQ(0, close(fd));
}
+static int
+scandir_none(const struct dirent *ent __unused)
+{
+ return (0);
+}
+
+ATF_TC(scandir_none);
+ATF_TC_HEAD(scandir_none, tc)
+{
+ atf_tc_set_md_var(tc, "descr",
+ "Test scandir() when no entries are selected");
+}
+ATF_TC_BODY(scandir_none, tc)
+{
+ struct dirent **namelist = NULL;
+
+ ATF_REQUIRE_EQ(0, scandir(".", &namelist, scandir_none, alphasort));
+ ATF_REQUIRE(namelist);
+ free(namelist);
+}
+
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, scandir_test);
ATF_TP_ADD_TC(tp, fscandir_test);
ATF_TP_ADD_TC(tp, scandirat_test);
+ ATF_TP_ADD_TC(tp, scandir_none);
return (atf_no_error());
}