>From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Luca Kellermann Date: Mon, 21 Jul 2025 00:18:39 +0200 Subject: [PATCH v3 1/6] scandir: hide that errno is set to 0 POSIX.1-2024 requires that standard functions don't set errno to 0. commit dae17a1aaf25d8333e729173d86659066607d87d ensured that cmp() and the caller of scandir() cannot observe that errno is set to 0 internally. however, this was not yet the case for the sel() callback. the following program demonstrates the issue: #include #include #include #include #include static int sel(const struct dirent *e) { /* XSH errno / XSH 2.3 Error Numbers: "No function in this * volume of POSIX.1-2024 shall set errno to [0 / zero]." */ assert(errno != 0); return 1; } int main(void) { /* XSH errno: "The value of errno in the initial thread shall * be zero at program startup [...]" */ assert(errno == 0); errno = 1; struct dirent **es = 0; int n = scandir(".", &es, sel, alphasort); if (n == -1) { perror("scandir"); exit(EXIT_FAILURE); } while (n > 0) free(es[--n]); free(es); } $ ./scandir-errno Assertion failed: errno != 0 (scandir-errno.c: sel: 10) Aborted (core dumped) --- src/dirent/scandir.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/dirent/scandir.c b/src/dirent/scandir.c index 7456b9b8bcec48f28500b3bc354736ca2d89f3a0..eead7e508ae9c68a067977293aabb52d23eabe93 100644 --- a/src/dirent/scandir.c +++ b/src/dirent/scandir.c @@ -17,7 +17,11 @@ int scandir(const char *path, struct dirent ***res, if (!d) return -1; while ((errno=0), (de = readdir(d))) { - if (sel && !sel(de)) continue; + if (sel) { + /* sel() must not observe that errno was set to 0. */ + errno = old_errno; + if (!sel(de)) continue; + } if (cnt >= len) { len = 2*len+1; if (len > SIZE_MAX/sizeof *names) break; @@ -37,6 +41,7 @@ int scandir(const char *path, struct dirent ***res, free(names); return -1; } + /* cmp() and caller must not observe that errno was set to 0. */ errno = old_errno; if (cmp) qsort(names, cnt, sizeof *names, (int (*)(const void *, const void *))cmp);