# HG changeset patch # User Bram Moolenaar # Date 1559817005 -7200 # Node ID efd36a9052cc2b4035300d1a9c7cca0386e5d8cf # Parent d23afa4d8b635474135b20abed82c7dfcecb89b5 patch 8.1.1473: new resolve() implementation causes problem for plugins commit https://github.com/vim/vim/commit/4a792c87b9a643a949ee36106a2f7e971dc633f8 Author: Bram Moolenaar Date: Thu Jun 6 12:22:41 2019 +0200 patch 8.1.1473: new resolve() implementation causes problem for plugins Problem: New resolve() implementation causes problem for plugins. Solution: Only resolve a resparse point after checking it is needed. (Ken Takata, closes #4492) diff --git a/src/os_mswin.c b/src/os_mswin.c --- a/src/os_mswin.c +++ b/src/os_mswin.c @@ -1753,6 +1753,39 @@ typedef BOOL (WINAPI *pfnGetVolumeInform DWORD nFileSystemNameSize); static pfnGetVolumeInformationByHandleW pGetVolumeInformationByHandleW = NULL; +# define is_path_sep(c) ((c) == L'\\' || (c) == L'/') + + static int +is_reparse_point_included(LPCWSTR fname) +{ + LPCWSTR p = fname, q; + WCHAR buf[MAX_PATH]; + DWORD attr; + + if (isalpha(p[0]) && p[1] == L':' && is_path_sep(p[2])) + p += 3; + else if (is_path_sep(p[0]) && is_path_sep(p[1])) + p += 2; + + while (*p != L'\0') + { + q = wcspbrk(p, L"\\/"); + if (q == NULL) + p = q = fname + wcslen(fname); + else + p = q + 1; + if (q - fname >= MAX_PATH) + return FALSE; + wcsncpy(buf, fname, q - fname); + buf[q - fname] = L'\0'; + attr = GetFileAttributesW(buf); + if (attr != INVALID_FILE_ATTRIBUTES + && (attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) + return TRUE; + } + return FALSE; +} + static char_u * resolve_reparse_point(char_u *fname) { @@ -1787,6 +1820,12 @@ resolve_reparse_point(char_u *fname) if (p == NULL) goto fail; + if (!is_reparse_point_included(p)) + { + vim_free(p); + goto fail; + } + h = CreateFileW(p, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); vim_free(p); diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -276,6 +276,7 @@ func Test_resolve_win32() " test for symbolic link to a file new Xfile wq + call assert_equal('Xfile', resolve('Xfile')) silent !mklink Xlink Xfile if !v:shell_error call assert_equal(s:normalize_fname(getcwd() . '\Xfile'), s:normalize_fname(resolve('./Xlink'))) @@ -333,11 +334,14 @@ func Test_resolve_win32() " test for reparse point call mkdir('Xdir') + call assert_equal('Xdir', resolve('Xdir')) silent !mklink /D Xdirlink Xdir if !v:shell_error w Xdir/text.txt + call assert_equal('Xdir/text.txt', resolve('Xdir/text.txt')) call assert_equal(s:normalize_fname(getcwd() . '\Xdir\text.txt'), s:normalize_fname(resolve('Xdirlink\text.txt'))) call assert_equal(s:normalize_fname(getcwd() . '\Xdir'), s:normalize_fname(resolve('Xdirlink'))) + call delete('Xdirlink') else echomsg 'skipped test for reparse point' endif diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -768,6 +768,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1473, +/**/ 1472, /**/ 1471,