Reset all Uri fields when reusing an instance (#41324)
authorMiha Zupan <mihazupan.zupan1@gmail.com>
Wed, 26 Aug 2020 13:08:29 +0000 (15:08 +0200)
committerGitHub <noreply@github.com>
Wed, 26 Aug 2020 13:08:29 +0000 (15:08 +0200)
* Reset all Uri fields when reusing an instance

* Test combined Uri's AbsoluteUri

src/libraries/System.Private.Uri/src/System/Uri.cs
src/libraries/System.Private.Uri/src/System/UriExt.cs
src/libraries/System.Private.Uri/tests/FunctionalTests/UriTests.cs

index 1ed1369..754ac60 100644 (file)
@@ -504,6 +504,7 @@ namespace System
             _flags = Flags.Zero;
             _info = null!;
             _syntax = null!;
+            _originalUnicodeString = null!;
             // If not resolved, we reparse modified Uri string and populate Uri internal data.
             CreateThis(relativeUri, dontEscape, UriKind.Absolute);
         }
@@ -550,6 +551,7 @@ namespace System
             _flags = Flags.Zero;
             _info = null!;
             _syntax = null!;
+            _originalUnicodeString = null!;
             CreateThis(newUriString, dontEscape, UriKind.Absolute);
             DebugSetLeftCtor();
         }
index 3b4504a..ff74af2 100644 (file)
@@ -26,6 +26,8 @@ namespace System
 
             _string = uri ?? string.Empty;
 
+            Debug.Assert(_originalUnicodeString is null && _info is null && _syntax is null && _flags == Flags.Zero);
+
             if (dontEscape)
                 _flags |= Flags.UserEscaped;
 
index 5dea3b3..2b2222f 100644 (file)
@@ -710,6 +710,25 @@ namespace System.PrivateUri.Tests
         }
 
         [Fact]
+        public static void Uri_CombineUsesNewUriString()
+        {
+            // Tests that internal Uri fields were properly reset during a Combine operation
+            // Otherwise, the wrong Uri string would be used if the relative Uri contains non-ascii characters
+            // This will only affect parsers without the IriParsing flag - only custom parsers
+            UriParser.Register(new GenericUriParser(GenericUriParserOptions.GenericAuthority), "combine-scheme", -1);
+
+            const string BaseUriString = "combine-scheme://foo";
+            const string RelativeUriString = "/relative/uri/with/non/ascii/\u00FC";
+            const string Combined = BaseUriString + "/relative/uri/with/non/ascii/%C3%BC";
+
+            var baseUri = new Uri(BaseUriString, UriKind.Absolute);
+            var relativeUri = new Uri(RelativeUriString, UriKind.Relative);
+
+            Assert.Equal(Combined, new Uri(baseUri, relativeUri).AbsoluteUri);
+            Assert.Equal(Combined, new Uri(baseUri, RelativeUriString).AbsoluteUri);
+        }
+
+        [Fact]
         public static void Uri_CachesIdnHost()
         {
             var uri = new Uri("https://\u00FCnicode/foo");