]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.2104: readdirex() might be slow v9.1.2104
authorYasuhiro Matsumoto <mattn.jp@gmail.com>
Wed, 21 Jan 2026 20:29:53 +0000 (20:29 +0000)
committerChristian Brabandt <cb@256bit.org>
Wed, 21 Jan 2026 20:29:53 +0000 (20:29 +0000)
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 <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/fileio.c
src/version.c

index feb538655dc01902e60c9f2de35b7f19a9f1f238..e637ab397f1f73c2e8fe1be12bde549aa8b9767f 100644 (file)
@@ -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))
     {
index 47ae372a42ae81c0d472bd9ffd85b776acb36955..30c54f9f23cf9dd4ff005c05a79cbb7ee1454546 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2104,
 /**/
     2103,
 /**/