]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.2004: MS-Windows: executable() cannot find file in directory with single... v9.1.2004
authorMuraoka Taro <koron.kaoriya@gmail.com>
Sun, 21 Dec 2025 19:19:39 +0000 (19:19 +0000)
committerChristian Brabandt <cb@256bit.org>
Sun, 21 Dec 2025 19:19:39 +0000 (19:19 +0000)
Problem:  MS-Windows: If a directory with a single character name is
          included in the PATH environment variable without a trailing
          path separator, executable() will not be able to find the
          executable file under it.
Solution: The second argument of the after_pathsep() function is now
          passed the next pointer where a path separator may exist
          (Muraoka Taro).

As a specific example, the default installation path for PowerShell v7
is "C:\Program Files\PowerShell\7", but if you set this as is in the
PATH environment variable, Vim will not be able to find the pwsh.exe
command. In this case, Vim will try to search for "C:\Program
Files\PowerShell\7pwsh.exe".

Cause: The after_pathsep() function determines whether the location
passed as its second argument immediately follows a path separator.
However, in the code where the problem occurred, the second argument was
passed a location that might contain a path separator. As a result, it
was mistakenly determined that a path separator was present in cases
where the final directory name was a single character and not followed
by a path separator, and the path to search was incorrect.

closes: #18979

Signed-off-by: Muraoka Taro <koron.kaoriya@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/os_win32.c
src/testdir/test_functions.vim
src/version.c

index 21b7023fa39a23ff09082e132207d80292210879..ede7a15b299533383a845ccdbb67a7056c916299 100644 (file)
@@ -2920,7 +2920,7 @@ executable_exists(
                (char *)buf,
                sizeof(buf),
                "%.*s%s%s", (int)(e - p), p,
-               !after_pathsep(p, e - 1) ? PATHSEPSTR : "",
+               !after_pathsep(p, e) ? PATHSEPSTR : "",
                name);
        }
 
index 9d66985d6cf64e8d518e179f61b49b91cedf75ed..ec721d0579d82227862264eb8261d5bfb8588633 100644 (file)
@@ -2140,6 +2140,41 @@ func Test_executable_longname()
   call delete(fname)
 endfunc
 
+func Test_executable_single_character_dir()
+  call mkdir('Xpath', 'R')
+  call mkdir('Xpath/a')
+  call mkdir('Xpath/b')
+  call mkdir('Xpath/c')
+  if has('win32')
+    call writefile([], 'Xpath/a/Xcmd1.bat')
+    call writefile([], 'Xpath/b/Xcmd2.bat')
+    call writefile([], 'Xpath/c/Xcmd3.bat')
+    let sep = ';'
+  else
+    call writefile([], 'Xpath/a/Xcmd1')
+    call writefile([], 'Xpath/b/Xcmd2')
+    call writefile([], 'Xpath/c/Xcmd3')
+    call setfperm('Xpath/a/Xcmd1', 'rwxr-xr-x')
+    call setfperm('Xpath/b/Xcmd2', 'rwxr-xr-x')
+    call setfperm('Xpath/c/Xcmd3', 'rwxr-xr-x')
+    let sep = ':'
+  endif
+
+  let save_path = $PATH
+  " a: single character name without path seperator
+  " b: single character name with path seperator
+  " c: single character name without path seperator at last of PATH
+  let $PATH = [
+        \ fnamemodify('./Xpath/a', ':p:h'),
+        \ fnamemodify('./Xpath/b', ':p'),
+        \ fnamemodify('./Xpath/c', ':p:h')
+        \ ]->join(sep)
+  call assert_true(executable('Xcmd1'))
+  call assert_true(executable('Xcmd2'))
+  call assert_true(executable('Xcmd3'))
+  let $PATH = save_path
+endfunc
+
 func Test_hostname()
   let hostname_vim = hostname()
   if has('unix')
index fbadafea2b0a6842b61969d8e168bc1726ff0efe..a0cbb675e2282fb74b0d7d19ac7b41040155076b 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2004,
 /**/
     2003,
 /**/