Skip to content

Commit d20c35e

Browse files
rokonecMihaZupan
andauthored
Handle unicode in absolute URI path for combine. (#111710)
* Handle unicode in absolute URI path for combine. * Adding debug assert Co-authored-by: Miha Zupan <[email protected]>
1 parent 54f41ac commit d20c35e

File tree

2 files changed

+50
-18
lines changed

2 files changed

+50
-18
lines changed

src/libraries/System.Private.Uri/src/System/UriExt.cs

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,30 +1053,42 @@ private void CreateThisFromUri(Uri otherUri)
10531053
{
10541054
DebugAssertInCtor();
10551055

1056-
// Clone the other URI but develop own UriInfo member
1057-
_info = null!;
1058-
10591056
_flags = otherUri._flags;
1060-
if (InFact(Flags.MinimalUriInfoSet))
1057+
1058+
if (InFact(Flags.AllUriInfoSet))
1059+
{
1060+
// We can share it now without mutation concern, for since AllUriInfoSet it is immutable.
1061+
_info = otherUri._info;
1062+
}
1063+
else
10611064
{
1062-
_flags &= ~(Flags.MinimalUriInfoSet | Flags.AllUriInfoSet | Flags.IndexMask);
1063-
// Port / Path offset
1064-
int portIndex = otherUri._info.Offset.Path;
1065-
if (InFact(Flags.NotDefaultPort))
1065+
Debug.Assert(!InFact(Flags.HasUnicode) || otherUri.IsNotAbsoluteUri);
1066+
// Clone the other URI but develop own UriInfo member
1067+
// We cannot just reference otherUri._info as this UriInfo will be mutated later
1068+
// which could be happening concurrently and in a not thread safe manner.
1069+
_info = null!;
1070+
1071+
if (InFact(Flags.MinimalUriInfoSet))
10661072
{
1067-
// Find the start of the port. Account for non-canonical ports like :00123
1068-
while (otherUri._string[portIndex] != ':' && portIndex > otherUri._info.Offset.Host)
1073+
_flags &= ~(Flags.MinimalUriInfoSet | Flags.AllUriInfoSet | Flags.IndexMask);
1074+
// Port / Path offset
1075+
int portIndex = otherUri._info.Offset.Path;
1076+
if (InFact(Flags.NotDefaultPort))
10691077
{
1070-
portIndex--;
1071-
}
1072-
if (otherUri._string[portIndex] != ':')
1073-
{
1074-
// Something wrong with the NotDefaultPort flag. Reset to path index
1075-
Debug.Fail("Uri failed to locate custom port at index: " + portIndex);
1076-
portIndex = otherUri._info.Offset.Path;
1078+
// Find the start of the port. Account for non-canonical ports like :00123
1079+
while (otherUri._string[portIndex] != ':' && portIndex > otherUri._info.Offset.Host)
1080+
{
1081+
portIndex--;
1082+
}
1083+
if (otherUri._string[portIndex] != ':')
1084+
{
1085+
// Something wrong with the NotDefaultPort flag. Reset to path index
1086+
Debug.Fail("Uri failed to locate custom port at index: " + portIndex);
1087+
portIndex = otherUri._info.Offset.Path;
1088+
}
10771089
}
1090+
_flags |= (Flags)portIndex; // Port or path
10781091
}
1079-
_flags |= (Flags)portIndex; // Port or path
10801092
}
10811093

10821094
_syntax = otherUri._syntax;

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Collections.Generic;
5+
using System.Diagnostics.CodeAnalysis;
56
using System.Globalization;
67
using System.Threading;
78
using System.Threading.Tasks;
@@ -729,6 +730,25 @@ public static void Uri_CombineUsesNewUriString()
729730
Assert.Equal(Combined, new Uri(baseUri, RelativeUriString).AbsoluteUri);
730731
}
731732

733+
[Theory]
734+
[InlineData("http://bar/Testue/testImage.jpg", "http://bar/Testue/testImage.jpg", "http://bar/Testue/testImage.jpg", "bar")]
735+
[InlineData(@"\\nas\Testue\testImage.jpg", "file://nas/Testue/testImage.jpg", "file://nas/Testue/testImage.jpg", "nas")]
736+
// Tests that internal Uri info were properly applied during a Combine operation when URI contains non-ascii character.
737+
[InlineData("http://bar/Test\u00fc/testImage.jpg", "http://bar/Test\u00fc/testImage.jpg", "http://bar/Test%C3%BC/testImage.jpg", "bar")]
738+
[InlineData("\\\\nas\\Test\u00fc\\testImage.jpg", "file://nas/Test\u00fc/testImage.jpg", "file://nas/Test%C3%BC/testImage.jpg", "nas")]
739+
public static void Uri_CombineWithAbsoluteUriResultInAbsoluteSchemaIgnoringOriginalBase(string relativeUri, string expectedUri, string expectedAbsoluteUri, string expectedHost)
740+
{
741+
string baseUriString = "combine-scheme://foo";
742+
743+
var baseUri = new Uri(baseUriString, UriKind.Absolute);
744+
var uri = new Uri(relativeUri);
745+
var resultUri = new Uri(baseUri, uri);
746+
747+
Assert.Equal(expectedUri, resultUri.ToString());
748+
Assert.Equal(expectedAbsoluteUri, resultUri.AbsoluteUri);
749+
Assert.Equal(expectedHost, resultUri.Host);
750+
}
751+
732752
[Fact]
733753
public static void Uri_CachesIdnHost()
734754
{

0 commit comments

Comments
 (0)