git: 920b2183919e - main - readdir: Fix error check.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 11 Jul 2025 20:43:51 UTC
The branch main has been updated by des:
URL: https://cgit.FreeBSD.org/src/commit/?id=920b2183919e430cf85c4aa1fa337bfded12aee5
commit 920b2183919e430cf85c4aa1fa337bfded12aee5
Author: Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2025-07-11 20:43:20 +0000
Commit: Dag-Erling Smørgrav <des@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);
}