From 81f203af67bb0dfed1a55656496fd55211d98972 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Thu, 11 Aug 2022 12:30:48 +1200 Subject: [PATCH v2 2/2] Follow junction point chains in our stat() emulation. Commit c5cb8f3b supposed that we'd only ever have to follow junction points for one hop, because we don't construct longer chains of them ourselves. But when stat()ing a parent directory supplied by the user, we should really be able to cope with longer chains. Choose an arbitrary cap of 8, to match the minimum acceptable value of SYMLOOP_MAX from POSIX. --- src/port/win32stat.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/port/win32stat.c b/src/port/win32stat.c index 26443293d7..2ff42b9a90 100644 --- a/src/port/win32stat.c +++ b/src/port/win32stat.c @@ -184,16 +184,27 @@ _pglstat64(const char *name, struct stat *buf) int _pgstat64(const char *name, struct stat *buf) { + int loops = 0; int ret; ret = _pglstat64(name, buf); /* Do we need to follow a symlink (junction point)? */ - if (ret == 0 && S_ISLNK(buf->st_mode)) + while (ret == 0 && S_ISLNK(buf->st_mode)) { char next[MAXPGPATH]; ssize_t size; + if (++loops > 8) + { + /* + * Give up. The error for too many symlinks is supposed to be + * ELOOP, but Windows hasn't got it. + */ + errno = EIO; + return -1; + } + /* * _pglstat64() already called readlink() once to be able to fill in * st_size, and now we need to do it again to get the path to follow. @@ -219,17 +230,6 @@ _pgstat64(const char *name, struct stat *buf) next[size] = 0; ret = _pglstat64(next, buf); - if (ret == 0 && S_ISLNK(buf->st_mode)) - { - /* - * We're only prepared to go one hop, because we only expect to - * deal with the simple cases that we create. The error for too - * many symlinks is supposed to be ELOOP, but Windows hasn't got - * it. - */ - errno = EIO; - return -1; - } } return ret; -- 2.35.1