summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnirudh Agnihotry <anirudhagnihotry098@gmail.com>2018-03-12 16:47:47 -0700
committerGitHub <noreply@github.com>2018-03-12 16:47:47 -0700
commitf5ae6d14d9d49dbb9f4e97f605d2a5cceab04879 (patch)
tree8ee275766a96b4208487513b8e079f6d23d2404c
parent3af716ef2cc8d9bcfd9d11998b908994f4d4ceda (diff)
downloadcoreclr-f5ae6d14d9d49dbb9f4e97f605d2a5cceab04879.tar.gz
coreclr-f5ae6d14d9d49dbb9f4e97f605d2a5cceab04879.tar.bz2
coreclr-f5ae6d14d9d49dbb9f4e97f605d2a5cceab04879.zip
Missing Case In Remove Relative Segments (#16869)
-rw-r--r--src/mscorlib/shared/System/IO/Path.Unix.cs2
-rw-r--r--src/mscorlib/shared/System/IO/Path.Windows.cs10
-rw-r--r--src/mscorlib/shared/System/IO/PathInternal.cs15
3 files changed, 17 insertions, 10 deletions
diff --git a/src/mscorlib/shared/System/IO/Path.Unix.cs b/src/mscorlib/shared/System/IO/Path.Unix.cs
index 10d295fece..f364b84df0 100644
--- a/src/mscorlib/shared/System/IO/Path.Unix.cs
+++ b/src/mscorlib/shared/System/IO/Path.Unix.cs
@@ -34,7 +34,7 @@ namespace System.IO
// We would ideally use realpath to do this, but it resolves symlinks, requires that the file actually exist,
// and turns it into a full path, which we only want if fullCheck is true.
- string collapsedString = PathInternal.RemoveRelativeSegments(path);
+ string collapsedString = PathInternal.RemoveRelativeSegments(path, PathInternal.GetRootLength(path));
Debug.Assert(collapsedString.Length < path.Length || collapsedString.ToString() == path,
"Either we've removed characters, or the string should be unmodified from the input path.");
diff --git a/src/mscorlib/shared/System/IO/Path.Windows.cs b/src/mscorlib/shared/System/IO/Path.Windows.cs
index 945bba3f4e..1934e8d502 100644
--- a/src/mscorlib/shared/System/IO/Path.Windows.cs
+++ b/src/mscorlib/shared/System/IO/Path.Windows.cs
@@ -117,12 +117,12 @@ namespace System.IO
combinedPath = JoinInternal(basePath, path);
}
- // Device paths are normalized by definition, so passing something of this format
- // to GetFullPath() won't do anything by design. Additionally, GetFullPathName() in
- // Windows doesn't root them properly. As such we need to manually remove segments.
+ // Device paths are normalized by definition, so passing something of this format (i.e. \\?\C:\.\tmp, \\.\C:\foo)
+ // to Windows APIs won't do anything by design. Additionally, GetFullPathName() in Windows doesn't root
+ // them properly. As such we need to manually remove segments and not use GetFullPath().
+
return PathInternal.IsDevice(combinedPath)
- // Paths at this point are in the form of \\?\C:\.\tmp we skip to the last character of the root when calling RemoveRelativeSegments to remove relative paths in such cases.
- ? PathInternal.RemoveRelativeSegments(combinedPath, PathInternal.GetRootLength(combinedPath) - 1)
+ ? PathInternal.RemoveRelativeSegments(combinedPath, PathInternal.GetRootLength(combinedPath))
: GetFullPath(combinedPath);
}
diff --git a/src/mscorlib/shared/System/IO/PathInternal.cs b/src/mscorlib/shared/System/IO/PathInternal.cs
index 059f0cf0b9..c5cce00b8f 100644
--- a/src/mscorlib/shared/System/IO/PathInternal.cs
+++ b/src/mscorlib/shared/System/IO/PathInternal.cs
@@ -113,12 +113,19 @@ namespace System.IO
/// <summary>
/// Try to remove relative segments from the given path (without combining with a root).
/// </summary>
- /// <param name="skip">Skip the specified number of characters before evaluating.</param>
- internal static string RemoveRelativeSegments(string path, int skip = 0)
+ /// <param name="rootLength">The length of the root of the given path</param>
+ internal static string RemoveRelativeSegments(string path, int rootLength)
{
- Debug.Assert(skip >= 0);
+ Debug.Assert(rootLength > 0);
bool flippedSeparator = false;
+ int skip = rootLength;
+ // We treat "\.." , "\." and "\\" as a relative segment. We want to collapse the first separator past the root presuming
+ // the root actually ends in a separator. Otherwise the first segment for RemoveRelativeSegments
+ // in cases like "\\?\C:\.\" and "\\?\C:\..\", the first segment after the root will be ".\" and "..\" which is not considered as a relative segment and hence not be removed.
+ if (path[skip - 1] == '\\')
+ skip--;
+
Span<char> initialBuffer = stackalloc char[260 /* PathInternal.MaxShortPath */];
ValueStringBuilder sb = new ValueStringBuilder(initialBuffer);
@@ -195,7 +202,7 @@ namespace System.IO
return path;
}
- return sb.ToString();
+ return sb.Length < rootLength ? path.Substring(0, rootLength) : sb.ToString();
}
}
}