|
|
Message-ID: <20250710185131.186-1-mailto.luca.kellermann@gmail.com>
Date: Thu, 10 Jul 2025 20:51:28 +0200
From: Luca Kellermann <mailto.luca.kellermann@...il.com>
To: musl@...ts.openwall.com
Subject: [PATCH 1/4] 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 <assert.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
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 7456b9b8..eead7e50 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);
--
2.43.0
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.