From: Yasuhiro Matsumoto Date: Wed, 21 Jan 2026 20:29:53 +0000 (+0000) Subject: patch 9.1.2104: readdirex() might be slow X-Git-Tag: v9.1.2104^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e89d97aaea0e2e94e07e24271976d0a8d2e23c38;p=thirdparty%2Fvim.git patch 9.1.2104: readdirex() might be slow Problem: readdirex() might be slow (Mao-Yining) Solution: Avoid double slash in path concatenation in create_readdirex_item() (Yasuhiro Matsumoto) On Cygwin and MSYS2, // has a special meaning: it is treated as a prefix for accessing network computers. For example, //wsl$/ is used to access WSL. In the current Vim implementation, the directory path passed to readdirex() and the file name found during traversal are concatenated using "/". When the directory path already ends with /, this results in paths like: "/" + "/" + "$Recycle.Bin" which produces a //-prefixed path. Such paths are interpreted as network paths, so Vim ends up trying to retrieve the file size of a network computer named $Recycle.Bin, which is not intended. From a correctness perspective on Windows, file size retrieval should be skipped for paths of the following forms: //host //host/share However, as a first step, we should avoid generating // paths caused by redundant / concatenation in the first place. This change addresses this by preventing unnecessary / insertion when constructing paths. fixes: #19188 closes: #19241 Signed-off-by: Yasuhiro Matsumoto Signed-off-by: Christian Brabandt --- diff --git a/src/fileio.c b/src/fileio.c index feb538655d..e637ab397f 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -4822,7 +4822,7 @@ create_readdirex_item(char_u *path, char_u *name) { dict_T *item; char *p; - size_t len; + size_t pathlen, len; stat_T st; int ret, link = FALSE; varnumber_T size; @@ -4836,11 +4836,15 @@ create_readdirex_item(char_u *path, char_u *name) return NULL; item->dv_refcount++; - len = STRLEN(path) + 1 + STRLEN(name) + 1; + pathlen = STRLEN(path); + len = pathlen + 1 + STRLEN(name) + 1; p = alloc(len); if (p == NULL) goto theend; - vim_snprintf(p, len, "%s/%s", path, name); + if (pathlen > 0 && path[pathlen - 1] == '/') + vim_snprintf(p, len, "%s%s", path, name); + else + vim_snprintf(p, len, "%s/%s", path, name); ret = mch_lstat(p, &st); if (ret >= 0 && S_ISLNK(st.st_mode)) { diff --git a/src/version.c b/src/version.c index 47ae372a42..30c54f9f23 100644 --- a/src/version.c +++ b/src/version.c @@ -734,6 +734,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 2104, /**/ 2103, /**/