From: Jeremy Kuhne Date: Thu, 1 Mar 2018 00:54:35 +0000 (-0800) Subject: Fix GetPathRoot issues (dotnet/corefx#27572) X-Git-Tag: accepted/tizen/unified/20190422.045933~2819 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3a95c15cc1c6f66b05392142451fa0200fb8c004;p=platform%2Fupstream%2Fcoreclr.git Fix GetPathRoot issues (dotnet/corefx#27572) Signed-off-by: dotnet-bot-corefx-mirror --- diff --git a/src/mscorlib/shared/System/IO/PathInternal.Windows.cs b/src/mscorlib/shared/System/IO/PathInternal.Windows.cs index f931380..2ef6669 100644 --- a/src/mscorlib/shared/System/IO/PathInternal.Windows.cs +++ b/src/mscorlib/shared/System/IO/PathInternal.Windows.cs @@ -188,64 +188,57 @@ namespace System.IO { int pathLength = path.Length; int i = 0; - int volumeSeparatorLength = 2; // Length to the colon "C:" - int uncRootLength = 2; // Length to the start of the server name "\\" - int devicePrefixLength = PathInternal.ExtendedPathPrefix.Length; bool deviceSyntax = IsDevice(path); bool deviceUnc = deviceSyntax && IsDeviceUNC(path); - if (deviceSyntax) - { - // Shift the position we look for the root from to account for the extended prefix - if (deviceUnc) - { - // "\\" -> "\\?\UNC\" - uncRootLength = UncExtendedPathPrefix.Length; - } - else if (devicePrefixLength + 1 < pathLength && path[devicePrefixLength + 1] == VolumeSeparatorChar && IsValidDriveChar(path[devicePrefixLength])) - { - // "C:" -> "\\?\C:" - volumeSeparatorLength += devicePrefixLength; - } - } if ((!deviceSyntax || deviceUnc) && pathLength > 0 && IsDirectorySeparator(path[0])) { // UNC or simple rooted path (e.g. "\foo", NOT "\\?\C:\foo") - - i = 1; // Drive rooted (\foo) is one character if (deviceUnc || (pathLength > 1 && IsDirectorySeparator(path[1]))) { - // UNC (\\?\UNC\ or \\), scan past the next two directory separators at most - // (e.g. to \\?\UNC\Server\Share or \\Server\Share\) - i = uncRootLength; - int n = 2; // Maximum separators to skip + // UNC (\\?\UNC\ or \\), scan past server\share + + // Start past the prefix ("\\" or "\\?\UNC\") + i = deviceUnc ? UncExtendedPrefixLength : UncPrefixLength; + + // Skip two separators at most + int n = 2; while (i < pathLength && (!IsDirectorySeparator(path[i]) || --n > 0)) i++; } + else + { + // Current drive rooted (e.g. "\foo") + i = 1; + } } - else if (pathLength >= volumeSeparatorLength - && path[volumeSeparatorLength - 1] == VolumeSeparatorChar - && IsValidDriveChar(path[volumeSeparatorLength - 2])) + else if (deviceSyntax) { - // Path is at least longer than where we expect a colon, and has a colon (\\?\A:, A:) - // If the colon is followed by a directory separator, move past it - i = volumeSeparatorLength; - if (pathLength >= volumeSeparatorLength + 1 && IsDirectorySeparator(path[volumeSeparatorLength])) + // Device path (e.g. "\\?\.", "\\.\") + // Skip any characters following the prefix that aren't a separator + i = DevicePrefixLength; + while (i < pathLength && !IsDirectorySeparator(path[i])) + i++; + + // If there is another separator take it, as long as we have had at least one + // non-separator after the prefix (e.g. don't take "\\?\\", but take "\\?\a\") + if (i < pathLength && i > DevicePrefixLength && IsDirectorySeparator(path[i])) i++; } - else if (deviceSyntax && ((devicePrefixLength + 1 >= pathLength) || !(path[devicePrefixLength + 1] == VolumeSeparatorChar))) + else if (pathLength >= 2 + && path[1] == VolumeSeparatorChar + && IsValidDriveChar(path[0])) { - i = devicePrefixLength; - int n = 1; // Maximum separators to skip - while (i < pathLength && (!IsDirectorySeparator(path[i]) || --n > 0)) - i++; + // Valid drive specified path ("C:", "D:", etc.) + i = 2; - if (i == devicePrefixLength) - i--; + // If the colon is followed by a directory separator, move past it (e.g "C:\") + if (pathLength > 2 && IsDirectorySeparator(path[2])) + i++; } - return (i < pathLength && IsDirectorySeparator(path[i])) ? i + 1 : i; + return i; } private static bool StartsWithOrdinal(ReadOnlySpan source, string value)