mailing list of musl libc
 help / color / mirror / code / Atom feed
* scandir qsort usage
@ 2025-07-12 14:50 Rich Felker
  2026-02-27 20:17 ` [musl] [PATCH] scandir: fix " Luca Kellermann
  0 siblings, 1 reply; 2+ messages in thread
From: Rich Felker @ 2025-07-12 14:50 UTC (permalink / raw)
  To: musl

The scandir fixes thread prompted me to notice that scandir is
invoking UB calling qsort with mismatched cmp function type. This was
unavoidable without fully duplicating qsort code in the past, but now
that we have qsort_r, it's fixable. If no one beats me to it I'll work
on a patch to fix this too.

Rich


^ permalink raw reply	[flat|nested] 2+ messages in thread

* [musl] [PATCH] scandir: fix qsort usage
  2025-07-12 14:50 scandir qsort usage Rich Felker
@ 2026-02-27 20:17 ` Luca Kellermann
  0 siblings, 0 replies; 2+ messages in thread
From: Luca Kellermann @ 2026-02-27 20:17 UTC (permalink / raw)
  To: Rich Felker; +Cc: musl

calling qsort() with a pointer to a function whose type is not
compatible with int(const void *, const void *) results in UB because
qsort() would call this function with an incompatible type.

avoid this by using qsort_r(). this is similar to how qsort() is
implemented on top of qsort_r().

the casts to void * in wrapper_cmp() are required because scandir()
takes int (*)(const struct dirent **, const struct dirent **) and not
int (*)(const struct dirent *const *, const struct dirent *const *).
---
Since you haven't posted a patch yet, I went ahead and fixed this. The
patch is based on the scandir() patch series I submitted in July.

 src/dirent/scandir.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/dirent/scandir.c b/src/dirent/scandir.c
index 9e4e623f..993e0c8b 100644
--- a/src/dirent/scandir.c
+++ b/src/dirent/scandir.c
@@ -7,9 +7,15 @@
 #include <errno.h>
 #include <stddef.h>
 
+typedef int (*cmpfun)(const struct dirent **, const struct dirent **);
+
+static int wrapper_cmp(const void *de1, const void *de2, void *cmp)
+{
+	return ((cmpfun)cmp)((void *)de1, (void *)de2);
+}
+
 int scandir(const char *path, struct dirent ***res,
-	int (*sel)(const struct dirent *),
-	int (*cmp)(const struct dirent **, const struct dirent **))
+	int (*sel)(const struct dirent *), cmpfun cmp)
 {
 	DIR *d;
 	struct dirent *de, **names=0, **tmp;
@@ -70,7 +76,7 @@ int scandir(const char *path, struct dirent ***res,
 	/* 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);
+	if (cmp) __qsort_r(names, cnt, sizeof *names, wrapper_cmp, (void *)cmp);
 	*res = names;
 	return cnt;
 }

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-02-27 20:19 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-12 14:50 scandir qsort usage Rich Felker
2026-02-27 20:17 ` [musl] [PATCH] scandir: fix " Luca Kellermann

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).