Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: [Bug] Strange Globing Behaviour when used with sudo
> 2018/06/01 03:15, Daniel Tameling <tamelingdaniel@xxxxxxxxx> wrote:
>
> As s is NULL and buf is in the example ./file/, statfullpath adds to
> buf a . so that it's "./file/.".
(snip)
> So one possibility to fix this is to
> call stat before adding the . to ./file/, and the return non-zero if
> it is not a directory.
Yes, but users can add '.' by themselves, for example
sudo zsh -c 'echo */.'. And of course you can not just
"return !S_ISDIR(st->st_mode)", and st may be NULL.
I've also fond that stat("file/..") is similarly broken.
In the patch below, I enclosed everything within "#ifdef __APPLE__"
to minimize the side effects. It is difficult to detect the bug
by configure since it requires sudo.
diff --git a/Src/glob.c b/Src/glob.c
index 66a95329f..95b3c7ca0 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -288,6 +288,26 @@ statfullpath(const char *s, struct stat *st, int l)
DPUTS(strlen(s) + !*s + pathpos - pathbufcwd >= PATH_MAX,
"BUG: statfullpath(): pathname too long");
strcpy(buf, pathbuf + pathbufcwd);
+
+#ifdef __APPLE__
+ /*
+ * Workaround for broken stat()/lstat()/access() on macOS.
+ * If called by root, these syscalls mistakenly return success for
+ * path like "foo/bar/." or "foo/bar/.." even if "bar" is a file.
+ * We should make sure "bar" is a directory.
+ */
+ if (!*s || !strcmp(s, ".") || !strcmp(s, "..")) {
+ struct stat stbuf;
+ if (stat(unmeta(buf), &stbuf) || !S_ISDIR(stbuf.st_mode))
+ return -1;
+ if (strcmp(s, "..")) { /* done if s is "" or "." */
+ if (st)
+ *st = stbuf;
+ return 0;
+ }
+ }
+#endif
+
strcpy(buf + pathpos - pathbufcwd, s);
if (!*s && *buf) {
/*
Messages sorted by:
Reverse Date,
Date,
Thread,
Author