The branch main has been updated by des:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=c187b673bb79905b5d5db1eb34d5a893c4464eeb

commit c187b673bb79905b5d5db1eb34d5a893c4464eeb
Author:     Dag-Erling Smørgrav <d...@freebsd.org>
AuthorDate: 2025-06-20 16:13:48 +0000
Commit:     Dag-Erling Smørgrav <d...@freebsd.org>
CommitDate: 2025-06-20 16:13:48 +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
---
 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 f74bd1f23613..21df9316d511 100644
--- a/lib/libc/gen/scandir.3
+++ b/lib/libc/gen/scandir.3
@@ -25,7 +25,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd June 19, 2025
+.Dd June 20, 2025
 .Dt SCANDIR 3
 .Os
 .Sh NAME
@@ -102,7 +102,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 172937392ddc..d8033a985862 100644
--- a/lib/libc/gen/scandir.c
+++ b/lib/libc/gen/scandir.c
@@ -74,9 +74,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());
 }

Reply via email to