<pre style='margin:0'>
Christopher Nielsen (mascguy) pushed a commit to branch master
in repository macports-legacy-support.
</pre>
<p><a href="https://github.com/macports/macports-legacy-support/commit/e8d226b22e8eef3501917cbb4513c79f1472511b">https://github.com/macports/macports-legacy-support/commit/e8d226b22e8eef3501917cbb4513c79f1472511b</a></p>
<pre style="white-space: pre; background: #F8F8F8"><span style='display:block; white-space:pre;color:#808000;'>commit e8d226b22e8eef3501917cbb4513c79f1472511b
</span>Author: Fred Wright <fw@fwright.net>
AuthorDate: Mon Nov 18 13:45:20 2024 -0800
<span style='display:block; white-space:pre;color:#404040;'> test_fdopendir: Add fstatat() buffer overrun defense.
</span><span style='display:block; white-space:pre;color:#404040;'>
</span><span style='display:block; white-space:pre;color:#404040;'> At the time of this writing, fstatat() may choose the wrong variant of
</span><span style='display:block; white-space:pre;color:#404040;'> stat to return, possibly overflowing the provided buffer. To defend
</span><span style='display:block; white-space:pre;color:#404040;'> against this, we make the buffer the larger of the two possible sizes,
</span><span style='display:block; white-space:pre;color:#404040;'> and also move it off the stack for less verbosity when debugging. See
</span><span style='display:block; white-space:pre;color:#404040;'> the comment in the code.
</span><span style='display:block; white-space:pre;color:#404040;'>
</span><span style='display:block; white-space:pre;color:#404040;'> TESTED:
</span><span style='display:block; white-space:pre;color:#404040;'> All versions pass, including previously crashing ino32 cases.
</span>---
test/test_fdopendir.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
<span style='display:block; white-space:pre;color:#808080;'>diff --git a/test/test_fdopendir.c b/test/test_fdopendir.c
</span><span style='display:block; white-space:pre;color:#808080;'>index 1f761ff..1712b30 100644
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>--- a/test/test_fdopendir.c
</span><span style='display:block; white-space:pre;background:#e0e0ff;'>+++ b/test/test_fdopendir.c
</span><span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -1,4 +1,3 @@
</span><span style='display:block; white-space:pre;background:#ffe0e0;'>-
</span> /*
* Copyright (c) 2019
* Copyright (C) 2023 raf <raf@raf.org>
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -28,6 +27,20 @@
</span> #include <sys/stat.h>
#include <sys/types.h>
<span style='display:block; white-space:pre;background:#e0ffe0;'>+/*
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * Buffer for fstatat() result. Due to possible confusion over which variant
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * should apply, we make it large enough for either variant. Since the
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * use of fstatat is only incidental to this test, and the data isn't actually
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * used, we don't bother checking for this confusion (and the related possible
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ * buffer overrun). A separate test should handle that.
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ */
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+static union stat_u {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct stat st;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#ifdef __DARWIN_STRUCT_STAT64
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ struct stat_64 __DARWIN_STRUCT_STAT64 st64;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+#endif
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+} stbuf;
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+
</span> /* Test expected failure case */
int check_failure(int fd, const char *name, const char *exp_sym, int exp_val)
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -51,7 +64,6 @@ int
</span> main(int argc, char *argv[])
{
int verbose = 0;
<span style='display:block; white-space:pre;background:#ffe0e0;'>- struct stat st;
</span> struct dirent *entry;
int dfd = -1;
DIR *dir;
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -84,7 +96,7 @@ main(int argc, char *argv[])
</span> return 1;
}
<span style='display:block; white-space:pre;background:#ffe0e0;'>- if (fstatat(dfd, entry->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (fstatat(dfd, entry->d_name, &stbuf.st, AT_SYMLINK_NOFOLLOW) < 0) {
</span> perror("error: fstatat after fdopendir failed");
fprintf(stderr, "dfd=%i d_name=%s\n", dfd, entry->d_name);
free(first_entry);
<span style='display:block; white-space:pre;background:#e0e0e0;'>@@ -193,7 +205,7 @@ main(int argc, char *argv[])
</span> if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
continue;
<span style='display:block; white-space:pre;background:#ffe0e0;'>- if (fstatat(dfd, entry->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
</span><span style='display:block; white-space:pre;background:#e0ffe0;'>+ if (fstatat(dfd, entry->d_name, &stbuf.st, AT_SYMLINK_NOFOLLOW) < 0) {
</span> perror("error: fstatat after opendir failed");
fprintf(stderr, "dfd=%i d_name=%s\n", dfd, entry->d_name);
(void)closedir(dir);
</pre><pre style='margin:0'>
</pre>