If the src path starts with the Win32 long path prefix \\?\ or the NT object directory prefix \??\, require the prefix to be followed by UNC\ or <drive letter>:\. Otherwise return EINVAL.
This fixes the assertion failure in symlink_info::check that was reported here: https://cygwin.com/ml/cygwin/2019-09/msg00228.html That assertion failure was caused by normalize_win32_path returning a path with no backslashes when the input src path was '\\?\DRIVE'. --- winsup/cygwin/path.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 2fbacd881..2eeb4fd1c 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1406,15 +1406,18 @@ normalize_win32_path (const char *src, char *dst, char *&tail) bool beg_src_slash = isdirsep (src[0]); tail = dst; - /* Skip long path name prefixes in Win32 or NT syntax. */ + /* Skip Win32 long path name prefix and NT object directory prefix. */ if (beg_src_slash && (src[1] == '?' || isdirsep (src[1])) && src[2] == '?' && isdirsep (src[3])) { src += 4; - if (src[1] != ':') /* native UNC path */ + if (src[1] == ':' && isdirsep (src[2])) + beg_src_slash = false; + else if (!strncmp (src, "UNC", 3) && isdirsep (src[3])) + /* native UNC path */ src += 2; /* Fortunately the first char is not copied... */ else - beg_src_slash = false; + return EINVAL; } if (beg_src_slash && isdirsep (src[1])) { -- 2.21.0