Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/mcs
diff options
context:
space:
mode:
authorKatelyn Gadd <kg@luminance.org>2017-10-20 11:53:25 +0300
committerMarek Safar <marek.safar@gmail.com>2017-10-20 11:53:25 +0300
commit44b21bca28f9d262e07ebd31c39829447582de5f (patch)
treee503b3e86227e6e1fd28d9004f89f2b6818d7bf0 /mcs
parentc26e069703d74e0b7a5da4b0326ae72cfde3f5d3 (diff)
Fix bug #58400 - incorrect implementation of LocalPath for file URLs (#5779)
Diffstat (limited to 'mcs')
-rw-r--r--mcs/class/System/Test/System/UriTest.cs20
-rw-r--r--mcs/class/System/Test/System/UriTest2.cs2
-rw-r--r--mcs/class/System/Test/System/UriTest3.cs32
-rw-r--r--mcs/class/referencesource/System/net/System/URI.cs51
4 files changed, 85 insertions, 20 deletions
diff --git a/mcs/class/System/Test/System/UriTest.cs b/mcs/class/System/Test/System/UriTest.cs
index 2db2fb21283..2cabd42af7b 100644
--- a/mcs/class/System/Test/System/UriTest.cs
+++ b/mcs/class/System/Test/System/UriTest.cs
@@ -502,20 +502,14 @@ namespace MonoTests.System
uri = new Uri ("file:////////cygwin/tmp/hello.txt");
Assert.AreEqual ("file://cygwin/tmp/hello.txt", uri.ToString (), "#3a");
- if (isWin32)
- Assert.AreEqual ("\\\\cygwin\\tmp\\hello.txt", uri.LocalPath, "#3b win32");
- else
- Assert.AreEqual ("/tmp/hello.txt", uri.LocalPath, "#3b *nix");
+ Assert.AreEqual ("\\\\cygwin\\tmp\\hello.txt", uri.LocalPath, "#3b win32");
Assert.AreEqual ("file", uri.Scheme, "#3c");
Assert.AreEqual ("cygwin", uri.Host, "#3d");
Assert.AreEqual ("/tmp/hello.txt", uri.AbsolutePath, "#3e");
uri = new Uri ("file://mymachine/cygwin/tmp/hello.txt");
Assert.AreEqual ("file://mymachine/cygwin/tmp/hello.txt", uri.ToString (), "#4a");
- if (isWin32)
- Assert.AreEqual ("\\\\mymachine\\cygwin\\tmp\\hello.txt", uri.LocalPath, "#4b win32");
- else
- Assert.AreEqual ("/cygwin/tmp/hello.txt", uri.LocalPath, "#4b *nix");
+ Assert.AreEqual ("\\\\mymachine\\cygwin\\tmp\\hello.txt", uri.LocalPath, "#4b win32");
Assert.AreEqual ("file", uri.Scheme, "#4c");
Assert.AreEqual ("mymachine", uri.Host, "#4d");
Assert.AreEqual ("/cygwin/tmp/hello.txt", uri.AbsolutePath, "#4e");
@@ -537,10 +531,7 @@ namespace MonoTests.System
Assert.AreEqual ("/", uri.AbsolutePath, "#6e");
Assert.AreEqual ("/", uri.PathAndQuery, "#6f");
Assert.AreEqual ("file://one_file.txt/", uri.GetLeftPart (UriPartial.Path), "#6g");
- if (isWin32)
- Assert.AreEqual ("\\\\one_file.txt", uri.LocalPath, "#6b");
- else
- Assert.AreEqual ("/", uri.LocalPath, "#6b");
+ Assert.AreEqual ("\\\\one_file.txt", uri.LocalPath, "#6b");
Assert.AreEqual ("file", uri.Scheme, "#6c");
Assert.AreEqual ("one_file.txt", uri.Host, "#6d");
@@ -551,10 +542,7 @@ namespace MonoTests.System
Assert.AreEqual ("/", uri.AbsolutePath, "#7e");
Assert.AreEqual ("/", uri.PathAndQuery, "#7f");
Assert.AreEqual ("file://one_file.txt/", uri.GetLeftPart (UriPartial.Path), "#7g");
- if (isWin32)
- Assert.AreEqual ("\\\\one_file.txt\\", uri.LocalPath, "#7b");
- else
- Assert.AreEqual ("/", uri.LocalPath, "#7b");
+ Assert.AreEqual ("\\\\one_file.txt\\", uri.LocalPath, "#7b");
Assert.AreEqual ("file", uri.Scheme, "#7c");
Assert.AreEqual ("one_file.txt", uri.Host, "#7d");
}
diff --git a/mcs/class/System/Test/System/UriTest2.cs b/mcs/class/System/Test/System/UriTest2.cs
index cbec7b2fc52..85eb8c712cf 100644
--- a/mcs/class/System/Test/System/UriTest2.cs
+++ b/mcs/class/System/Test/System/UriTest2.cs
@@ -875,7 +875,7 @@ TextWriter sw = Console.Out;
if (IriParsing) {
Assert.AreEqual ("/dir/subdir/file", uri.AbsolutePath, "AbsolutePath");
Assert.AreEqual ("file://host/dir/subdir/file?this-is-not-a-query#but-this-is-a-fragment", uri.AbsoluteUri, "AbsoluteUri");
- Assert.AreEqual (isWin32 ? "\\\\host\\dir\\subdir\\file" : "/dir/subdir/file", uri.LocalPath, "LocalPath");
+ Assert.AreEqual ("\\\\host\\dir\\subdir\\file", uri.LocalPath, "LocalPath");
Assert.AreEqual ("/dir/subdir/file?this-is-not-a-query", uri.PathAndQuery, "PathAndQuery");
Assert.AreEqual ("?this-is-not-a-query", uri.Query, "Query");
Assert.AreEqual ("file", uri.Segments [3], "Segments [3]");
diff --git a/mcs/class/System/Test/System/UriTest3.cs b/mcs/class/System/Test/System/UriTest3.cs
index a39ac73d0af..f83ec1c62d1 100644
--- a/mcs/class/System/Test/System/UriTest3.cs
+++ b/mcs/class/System/Test/System/UriTest3.cs
@@ -696,6 +696,38 @@ namespace MonoTests.System
type = Uri.CheckHostName ("3.141592653589793238462643383279502884197169399375105820974944592._om");
Assert.AreEqual (UriHostNameType.Unknown, type, "DomainLabelLength#3");
}
+
+ // https://bugzilla.xamarin.com/show_bug.cgi?id=58400
+ [Test]
+ public static void Test_LocalPath_Bug58400()
+ {
+ var uriAndExpected = new []
+ {
+ ("file://host/directory/filename", @"\\host\directory\filename"),
+ ("file://host/directory/", @"\\host\directory\"),
+ ("file://host/filename", @"\\host\filename"),
+ ("file://host/", @"\\host\"),
+ ("file://host", @"\\host"),
+ ("file:///directory/filename", "/directory/filename"),
+ ("file:///directory/", "/directory/"),
+ ("file:///filename", "/filename"),
+ ("file:///", "/"),
+ // This is an invalid URI, technically
+ ("file://", "/"),
+ ("file://////hello/world", @"\\hello\world"),
+ ("file://hello/////world", @"\\hello\\\\\world"),
+ };
+
+ foreach (var tup in uriAndExpected)
+ {
+ var originalUri = tup.Item1;
+ var expectedLocalPath = tup.Item2;
+ var uri = new Uri (originalUri);
+ var localPath = uri.LocalPath;
+
+ Assert.AreEqual (expectedLocalPath, localPath, originalUri);
+ }
+ }
}
}
diff --git a/mcs/class/referencesource/System/net/System/URI.cs b/mcs/class/referencesource/System/net/System/URI.cs
index 24ddbc66e15..8a740ce08b8 100644
--- a/mcs/class/referencesource/System/net/System/URI.cs
+++ b/mcs/class/referencesource/System/net/System/URI.cs
@@ -1070,11 +1070,50 @@ namespace System {
EnsureParseRemaining();
#if MONO
+ // https://bugzilla.xamarin.com/show_bug.cgi?id=58400
+ bool isFileUrlWithHost =
+ (m_Info.Offset.Host != m_Info.Offset.Path) &&
+ // only file URLs
+ IsFile &&
+ // Paths that got reinterpreted as files would be treated
+ // as if they have a host, like "/a/b" which maps to "file:///a/b/",
+ // or "C:\a\b\" which maps to "file:///c:/a/b"
+ OriginalString.StartsWith("file://", StringComparison.Ordinal) &&
+ // file://localhost/x/y needs to produce /x/y
+ !IsLoopback;
+
+ // Manually check for "hosts" that are just forward slashes.
+ if (isFileUrlWithHost) {
+ isFileUrlWithHost = false;
+
+ for (int i = m_Info.Offset.Host; i < m_Info.Offset.Path; i++) {
+ if (OriginalString[i] != '/') {
+ isFileUrlWithHost = true;
+ break;
+ }
+ }
+ }
+
+ // We need to force generation of a UNC-style path instead of a unix one,
+ // despite the path not being UNC originally
+ bool treatAsUncPath = IsUncPath || isFileUrlWithHost;
+
//
// I think this is wrong but it keeps LocalPath fully backward compatible
//
- if (IsUncOrDosPath && (IsWindowsFileSystem || !IsUncPath))
+ if (
+ (IsUncOrDosPath &&
+ (
+ IsWindowsFileSystem ||
+ !IsUncPath
+ )
+ ) ||
+ // If a path has a host name force it into this branch so the UNC code runs
+ isFileUrlWithHost
+ )
#else
+ bool treatAsUncPath = IsUncPath;
+
//Other cases will get a Unix-style path
if (IsUncOrDosPath)
#endif
@@ -1083,7 +1122,13 @@ namespace System {
int start;
// Do we have a valid local path right in m_string?
- if (NotAny(Flags.HostNotCanonical|Flags.PathNotCanonical|Flags.ShouldBeCompressed)) {
+ if (
+ NotAny(Flags.HostNotCanonical|Flags.PathNotCanonical|Flags.ShouldBeCompressed)
+#if MONO
+ // This branch drops the host name so we can't use it
+ && !isFileUrlWithHost
+#endif
+ ) {
start = IsUncPath? m_Info.Offset.Host-2 :m_Info.Offset.Path;
@@ -1121,7 +1166,7 @@ namespace System {
string host = m_Info.Host;
result = new char [host.Length + 3 + m_Info.Offset.Fragment - m_Info.Offset.Path ];
- if (IsUncPath)
+ if (treatAsUncPath)
{
result[0] = '\\';
result[1] = '\\';