The branch main has been updated by des: URL: https://cgit.FreeBSD.org/src/commit/?id=920b2183919e430cf85c4aa1fa337bfded12aee5
commit 920b2183919e430cf85c4aa1fa337bfded12aee5 Author: Dag-Erling Smørgrav <d...@freebsd.org> AuthorDate: 2025-07-11 20:43:20 +0000 Commit: Dag-Erling Smørgrav <d...@freebsd.org> CommitDate: 2025-07-11 20:43:32 +0000 readdir: Fix error check. Now that dd_size is unsigned, we need to check if the return value from getdirentries() was negative before assigning it to dd_size. While here, simplify the scandir_error test case slightly, and verify that calling readdir() again after EOF still returns NULL. Fixes: 42e613018da5 Sponsored by: Klara, Inc. Reviewed by: kevans Differential Revision: https://reviews.freebsd.org/D51266 --- lib/libc/gen/readdir.c | 7 +++++-- lib/libc/tests/gen/opendir_test.c | 1 + lib/libc/tests/gen/scandir_test.c | 12 +++++------- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c index 32603c0b4677..b70102954df1 100644 --- a/lib/libc/gen/readdir.c +++ b/lib/libc/gen/readdir.c @@ -50,6 +50,7 @@ _readdir_unlocked(DIR *dirp, int flags) struct dirent *dp; off_t initial_seek; size_t initial_loc = 0; + ssize_t ret; for (;;) { if (dirp->dd_loc >= dirp->dd_size) { @@ -61,11 +62,13 @@ _readdir_unlocked(DIR *dirp, int flags) } if (dirp->dd_loc == 0 && !(dirp->dd_flags & (__DTF_READALL | __DTF_SKIPREAD))) { + dirp->dd_size = 0; initial_seek = dirp->dd_seek; - dirp->dd_size = _getdirentries(dirp->dd_fd, + ret = _getdirentries(dirp->dd_fd, dirp->dd_buf, dirp->dd_len, &dirp->dd_seek); - if (dirp->dd_size <= 0) + if (ret <= 0) return (NULL); + dirp->dd_size = (size_t)ret; _fixtelldir(dirp, initial_seek, initial_loc); } dirp->dd_flags &= ~__DTF_SKIPREAD; diff --git a/lib/libc/tests/gen/opendir_test.c b/lib/libc/tests/gen/opendir_test.c index 89be2becc607..b7481255654f 100644 --- a/lib/libc/tests/gen/opendir_test.c +++ b/lib/libc/tests/gen/opendir_test.c @@ -46,6 +46,7 @@ opendir_check(const struct atf_tc *tc, DIR *dirp) ATF_CHECK_STREQ("subdir", ent->d_name); ATF_CHECK_EQ(DT_DIR, ent->d_type); ATF_CHECK(readdir(dirp) == NULL); + ATF_CHECK(readdir(dirp) == NULL); } ATF_TC(opendir_ok); diff --git a/lib/libc/tests/gen/scandir_test.c b/lib/libc/tests/gen/scandir_test.c index f7b52b5e3616..afd25bf7c0b2 100644 --- a/lib/libc/tests/gen/scandir_test.c +++ b/lib/libc/tests/gen/scandir_test.c @@ -157,7 +157,7 @@ ATF_TC_BODY(scandir_error, tc) { char path[16]; struct dirent **namelist = NULL; - int fd, i, ret; + int fd, i; ATF_REQUIRE_EQ(0, mkdir("dir", 0755)); for (i = 0; i < 1024; i++) { @@ -170,9 +170,8 @@ ATF_TC_BODY(scandir_error, tc) scandir_error_count = 0; scandir_error_fd = fd; scandir_error_select_return = 0; - ret = fdscandir(fd, &namelist, scandir_error_select, NULL); - ATF_CHECK_EQ(-1, ret); - ATF_CHECK_ERRNO(EBADF, ret < 0); + ATF_CHECK_ERRNO(EBADF, + fdscandir(fd, &namelist, scandir_error_select, NULL) < 0); ATF_CHECK_EQ(NULL, namelist); /* second pass, select everything */ @@ -180,9 +179,8 @@ ATF_TC_BODY(scandir_error, tc) scandir_error_count = 0; scandir_error_fd = fd; scandir_error_select_return = 1; - ret = fdscandir(fd, &namelist, scandir_error_select, NULL); - ATF_CHECK_EQ(-1, ret); - ATF_CHECK_ERRNO(EBADF, ret < 0); + ATF_CHECK_ERRNO(EBADF, + fdscandir(fd, &namelist, scandir_error_select, NULL) < 0); ATF_CHECK_EQ(NULL, namelist); }