diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 7acdf9970510fc..44d6d3c30833e5 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -8,79 +8,83 @@
https://github.com/dotnet/msquic
98129287d56a5e0348c291ce4260e630b4aa510d
-
+
https://github.com/dotnet/emsdk
- 5cac15def164fc5ab593f8a0d3159dc51acd3cdd
+ 9838ec0843442f761488cfec9cf34612c9f675e6
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
+
+
+ https://github.com/dotnet/arcade
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
https://github.com/microsoft/vstest
@@ -202,9 +206,9 @@
https://github.com/dotnet/xharness
e9669dc84ecd668d3bbb748758103e23b394ffef
-
+
https://github.com/dotnet/arcade
- 7324320f814152b72295946847ca72413507705a
+ dd9dbfedbdb31401bb16bba8366f31bbd382549b
https://dev.azure.com/dnceng/internal/_git/dotnet-optimization
diff --git a/eng/Versions.props b/eng/Versions.props
index 157120cdfad981..55b34e750e955b 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -53,20 +53,21 @@
1.0.0-rc.2.21419.17
- 6.0.0-beta.21460.7
- 6.0.0-beta.21460.7
- 6.0.0-beta.21460.7
- 6.0.0-beta.21460.7
- 6.0.0-beta.21460.7
- 6.0.0-beta.21460.7
- 2.5.1-beta.21460.7
- 6.0.0-beta.21460.7
- 6.0.0-beta.21460.7
- 6.0.0-beta.21460.7
- 6.0.0-beta.21460.7
- 6.0.0-beta.21460.7
- 6.0.0-beta.21460.7
- 6.0.0-beta.21460.7
+ 6.0.0-beta.21467.3
+ 6.0.0-beta.21467.3
+ 6.0.0-beta.21467.3
+ 6.0.0-beta.21467.3
+ 6.0.0-beta.21467.3
+ 6.0.0-beta.21467.3
+ 2.5.1-beta.21467.3
+ 6.0.0-beta.21467.3
+ 6.0.0-beta.21467.3
+ 6.0.0-beta.21467.3
+ 6.0.0-beta.21467.3
+ 6.0.0-beta.21467.3
+ 6.0.0-beta.21467.3
+ 6.0.0-beta.21467.3
+ 6.0.0-beta.21467.3
6.0.0-preview.1.102
@@ -166,7 +167,7 @@
2.14.3
6.0.100-rc.2.21463.12
- 5.0.0-preview-20201009.2
+ 6.0.0-preview-20210916.1
6.0.100-1.21459.1
$(MicrosoftNETILLinkTasksVersion)
@@ -184,7 +185,7 @@
11.1.0-alpha.1.21416.1
11.1.0-alpha.1.21416.1
- 6.0.0-rtm.21464.2
+ 6.0.0-rc.2.21464.1
$(MicrosoftNETWorkloadEmscriptenManifest60100Version)
1.1.87-gba258badda
diff --git a/global.json b/global.json
index 0cfd182128d924..79641b503fbb19 100644
--- a/global.json
+++ b/global.json
@@ -12,10 +12,10 @@
"python3": "3.7.1"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21460.7",
- "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21460.7",
- "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21460.7",
- "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21460.7",
+ "Microsoft.DotNet.Build.Tasks.TargetFramework.Sdk": "6.0.0-beta.21467.3",
+ "Microsoft.DotNet.Arcade.Sdk": "6.0.0-beta.21467.3",
+ "Microsoft.DotNet.Helix.Sdk": "6.0.0-beta.21467.3",
+ "Microsoft.DotNet.SharedFramework.Sdk": "6.0.0-beta.21467.3",
"Microsoft.Build.NoTargets": "3.1.0",
"Microsoft.Build.Traversal": "3.0.23",
"Microsoft.NET.Sdk.IL": "6.0.0-rc.1.21415.6"
diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp
index 61f0d827e60f19..dee4fe132fa74c 100644
--- a/src/coreclr/debug/daccess/daccess.cpp
+++ b/src/coreclr/debug/daccess/daccess.cpp
@@ -6077,13 +6077,20 @@ ClrDataAccess::GetMethodVarInfo(MethodDesc* methodDesc,
SUPPORTS_DAC;
COUNT_T countNativeVarInfo;
NewHolder nativeVars(NULL);
-
- NativeCodeVersion requestedNativeCodeVersion = ExecutionManager::GetNativeCodeVersion(address);
- if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == NULL)
+ TADDR nativeCodeStartAddr;
+ if (address != NULL)
{
- return E_INVALIDARG;
+ NativeCodeVersion requestedNativeCodeVersion = ExecutionManager::GetNativeCodeVersion(address);
+ if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ nativeCodeStartAddr = PCODEToPINSTR(requestedNativeCodeVersion.GetNativeCode());
+ }
+ else
+ {
+ nativeCodeStartAddr = PCODEToPINSTR(methodDesc->GetNativeCode());
}
- TADDR nativeCodeStartAddr = PCODEToPINSTR(requestedNativeCodeVersion.GetNativeCode());
DebugInfoRequest request;
request.InitFromStartingAddr(methodDesc, nativeCodeStartAddr);
@@ -6128,13 +6135,20 @@ ClrDataAccess::GetMethodNativeMap(MethodDesc* methodDesc,
// Use the DebugInfoStore to get IL->Native maps.
// It doesn't matter whether we're jitted, ngenned etc.
-
- NativeCodeVersion requestedNativeCodeVersion = ExecutionManager::GetNativeCodeVersion(address);
- if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == NULL)
+ TADDR nativeCodeStartAddr;
+ if (address != NULL)
{
- return E_INVALIDARG;
+ NativeCodeVersion requestedNativeCodeVersion = ExecutionManager::GetNativeCodeVersion(address);
+ if (requestedNativeCodeVersion.IsNull() || requestedNativeCodeVersion.GetNativeCode() == NULL)
+ {
+ return E_INVALIDARG;
+ }
+ nativeCodeStartAddr = PCODEToPINSTR(requestedNativeCodeVersion.GetNativeCode());
+ }
+ else
+ {
+ nativeCodeStartAddr = PCODEToPINSTR(methodDesc->GetNativeCode());
}
- TADDR nativeCodeStartAddr = PCODEToPINSTR(requestedNativeCodeVersion.GetNativeCode());
DebugInfoRequest request;
request.InitFromStartingAddr(methodDesc, nativeCodeStartAddr);
diff --git a/src/installer/pkg/sfx/installers/dotnet-host.proj b/src/installer/pkg/sfx/installers/dotnet-host.proj
index 953b0f4f8522f9..aba056f06d17cb 100644
--- a/src/installer/pkg/sfx/installers/dotnet-host.proj
+++ b/src/installer/pkg/sfx/installers/dotnet-host.proj
@@ -15,7 +15,7 @@
true
sharedhost
false
- osx_scripts/host
+ osx_scripts/host
The .NET Shared Host.
$(MSBuildThisFileDirectory)rpm_scripts/host
$(RpmScriptsDirectory)/after_install.sh
@@ -78,4 +78,36 @@
+
+
+ <_MacOSIntermediatesPath>$(IntermediateOutputPath)macos/
+
+ $(_MacOSIntermediatesPath)scripts
+
+
+ <_MacOSScript Include="$(MacOSScriptsTemplateDirectory)/*" Destination="$(MacOSScriptsDirectory)/%(FileName)%(Extension)"/>
+
+
+
+
+ <_UnameMachineRegex>$(InstallerTargetArchitecture)
+ <_UnameMachineRegex Condition="'$(InstallerTargetArchitecture)' == 'arm64'">arm64|aarch64
+ <_UnameMachineRegex Condition="'$(InstallerTargetArchitecture)' == 'x64'">amd64|x86_64
+ <_MacOSScriptsTemplateProperties>InstallerTargetArchitecture=$(InstallerTargetArchitecture);UnameMachineRegex=$(_UnameMachineRegex)
+
+
+
+
+
+
+
+
+
+
diff --git a/src/installer/pkg/sfx/installers/dotnet-hostfxr.proj b/src/installer/pkg/sfx/installers/dotnet-hostfxr.proj
index 2c5fa5d8188867..b9eb792a38fade 100644
--- a/src/installer/pkg/sfx/installers/dotnet-hostfxr.proj
+++ b/src/installer/pkg/sfx/installers/dotnet-hostfxr.proj
@@ -14,7 +14,6 @@
HostFxrSrc
true
hostfxr
- osx_scripts/hostfxr
The .NET HostFxr
diff --git a/src/installer/pkg/sfx/installers/host.wxs b/src/installer/pkg/sfx/installers/host.wxs
index 773246beb70f1a..91ca74c69914f7 100644
--- a/src/installer/pkg/sfx/installers/host.wxs
+++ b/src/installer/pkg/sfx/installers/host.wxs
@@ -5,7 +5,7 @@
-
+
-
+
+
+
+
-
+
+
+
+
+
+
+
+ NOT NON_NATIVE_ARCHITECTURE
+
+
+
+
+
-
+
@@ -47,6 +62,16 @@
+
+
+
+
-
-
+
+
+
+
+ NON_NATIVE_ARCHITECTURE
+
+
+
\ No newline at end of file
diff --git a/src/installer/pkg/sfx/installers/osx_scripts/host/postinstall b/src/installer/pkg/sfx/installers/osx_scripts/host/postinstall
index 531cb93fd382fc..eaee94e2798738 100755
--- a/src/installer/pkg/sfx/installers/osx_scripts/host/postinstall
+++ b/src/installer/pkg/sfx/installers/osx_scripts/host/postinstall
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
#
# Licensed to the .NET Foundation under one or more agreements.
# The .NET Foundation licenses this file to you under the MIT license.
@@ -10,9 +10,21 @@ INSTALL_DESTINATION=$2
# A temporary fix for the permissions issue(s)
chmod 755 $INSTALL_DESTINATION/dotnet
-# Add the installation directory to the system-wide paths
-# But first create the directory if it doesn't exist
-mkdir -p /etc/paths.d
-echo $INSTALL_DESTINATION | tee /etc/paths.d/dotnet
+if [ -e /etc/dotnet/install_location ]; then
+ # clear out any entries for this architecture if they exist
+ sed -i old '/^${InstallerTargetArchitecture}=/d' /etc/dotnet/install_location
+else
+ mkdir -p /etc/dotnet
+fi
+
+echo ${InstallerTargetArchitecture}=$INSTALL_DESTINATION | tee -a /etc/dotnet/install_location
+
+# if we're running on the native architecture
+if [[ "$(uname -m)" =~ "${UnameMachineRegex}" ]]; then
+ # Add the installation directory to the system-wide paths
+ # But first create the directory if it doesn't exist
+ mkdir -p /etc/paths.d
+ echo $INSTALL_DESTINATION | tee /etc/paths.d/dotnet
+fi
exit 0
diff --git a/src/installer/pkg/sfx/installers/osx_scripts/hostfxr/postinstall b/src/installer/pkg/sfx/installers/osx_scripts/hostfxr/postinstall
deleted file mode 100755
index 2d0ceb82786936..00000000000000
--- a/src/installer/pkg/sfx/installers/osx_scripts/hostfxr/postinstall
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-#
-# Licensed to the .NET Foundation under one or more agreements.
-# The .NET Foundation licenses this file to you under the MIT license.
-#
-
-PACKAGE=$1
-INSTALL_DESTINATION=$2
-
-# A temporary fix for the permissions issue(s)
-chmod 755 $INSTALL_DESTINATION/dotnet
-
-# Add the installation directory to the system-wide paths
-echo $INSTALL_DESTINATION | tee /etc/paths.d/dotnet
-
-exit 0
diff --git a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs
index b448bc79081e8d..93d7590059b310 100644
--- a/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs
+++ b/src/libraries/Microsoft.Extensions.Logging.Abstractions/gen/LoggerMessageGenerator.Parser.cs
@@ -438,11 +438,21 @@ public IReadOnlyList GetLogClasses(IEnumerable diagnostics = await RunGenerator(@"
+ using Microsoft.Extensions.Logging;
+
+ namespace MyLibrary;
+
+ internal partial class Logger
+ {
+ [LoggerMessage(EventId = 1, Level = LogLevel.Information, Message = ""Hello {Name}!"")]
+ public static partial void Greeting(ILogger logger, string name);
+ }
+ ");
+
+ Assert.Empty(diagnostics);
+ }
+
[Theory]
[InlineData("false")]
[InlineData("true")]
diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/openssl.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native/openssl.c
index 44fa7705c26ac9..c18eb0ffb7c6bb 100644
--- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/openssl.c
+++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/openssl.c
@@ -564,7 +564,7 @@ BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32_t forIssue
if (answer)
{
BIO* b = BIO_new(BIO_s_mem());
- ASN1_STRING_print_ex(b, answer, 0);
+ ASN1_STRING_print_ex(b, answer, ASN1_STRFLGS_UTF8_CONVERT);
return b;
}
}
@@ -646,7 +646,7 @@ BIO* CryptoNative_GetX509NameInfo(X509* x509, int32_t nameType, int32_t forIssue
if (str)
{
BIO* b = BIO_new(BIO_s_mem());
- ASN1_STRING_print_ex(b, str, 0);
+ ASN1_STRING_print_ex(b, str, ASN1_STRFLGS_UTF8_CONVERT);
sk_GENERAL_NAME_free(altNames);
return b;
}
diff --git a/src/libraries/System.Private.Uri/src/Resources/Strings.resx b/src/libraries/System.Private.Uri/src/Resources/Strings.resx
index 92a87cd44ccaa1..9975314e3d97c3 100644
--- a/src/libraries/System.Private.Uri/src/Resources/Strings.resx
+++ b/src/libraries/System.Private.Uri/src/Resources/Strings.resx
@@ -198,4 +198,7 @@
UriParser's base InitializeAndValidate may only be called once on a single Uri instance and only from an override of InitializeAndValidate.
+
+ GetComponents() may not be used for Path/Query on a Uri instance created with UriCreationOptions.DangerousDisablePathAndQueryCanonicalization.
+
\ No newline at end of file
diff --git a/src/libraries/System.Private.Uri/src/System.Private.Uri.csproj b/src/libraries/System.Private.Uri/src/System.Private.Uri.csproj
index 4b63c5b3cb3061..ce5a97d87051bf 100644
--- a/src/libraries/System.Private.Uri/src/System.Private.Uri.csproj
+++ b/src/libraries/System.Private.Uri/src/System.Private.Uri.csproj
@@ -24,6 +24,7 @@
+
diff --git a/src/libraries/System.Private.Uri/src/System/Uri.cs b/src/libraries/System.Private.Uri/src/System/Uri.cs
index ad6efdba8540d1..7d1b4d72201a38 100644
--- a/src/libraries/System.Private.Uri/src/System/Uri.cs
+++ b/src/libraries/System.Private.Uri/src/System/Uri.cs
@@ -121,6 +121,11 @@ internal enum Flags : ulong
IriCanonical = 0x78000000000,
UnixPath = 0x100000000000,
+ ///
+ /// Disables any validation/normalization past the authority. Fragments will always be empty. GetComponents will throw for Path/Query.
+ ///
+ DisablePathAndQueryCanonicalization = 0x200000000000,
+
///
/// Used to ensure that InitializeAndValidate is only called once per Uri instance and only from an override of InitializeAndValidate
///
@@ -267,6 +272,8 @@ internal static bool IriParsingStatic(UriParser? syntax)
return syntax is null || syntax.InFact(UriSyntaxFlags.AllowIriParsing);
}
+ internal bool DisablePathAndQueryCanonicalization => (_flags & Flags.DisablePathAndQueryCanonicalization) != 0;
+
internal bool UserDrivenParsing
{
get
@@ -410,6 +417,20 @@ public Uri(string uriString, UriKind uriKind)
DebugSetLeftCtor();
}
+ ///
+ /// Initializes a new instance of the class with the specified URI and additional .
+ ///
+ /// A string that identifies the resource to be represented by the instance.
+ /// Options that control how the is created and behaves.
+ public Uri(string uriString, in UriCreationOptions creationOptions)
+ {
+ if (uriString is null)
+ throw new ArgumentNullException(nameof(uriString));
+
+ CreateThis(uriString, false, UriKind.Absolute, in creationOptions);
+ DebugSetLeftCtor();
+ }
+
//
// Uri(Uri, string)
//
@@ -1639,6 +1660,9 @@ public override bool Equals([NotNullWhen(true)] object? comparand)
// canonicalize the comparand, making comparison possible
if (obj is null)
{
+ if (DisablePathAndQueryCanonicalization)
+ return false;
+
if (!(comparand is string s))
return false;
@@ -1649,6 +1673,9 @@ public override bool Equals([NotNullWhen(true)] object? comparand)
return false;
}
+ if (DisablePathAndQueryCanonicalization != obj.DisablePathAndQueryCanonicalization)
+ return false;
+
if (ReferenceEquals(OriginalString, obj.OriginalString))
{
return true;
@@ -2553,7 +2580,7 @@ private unsafe void GetHostViaCustomSyntax()
//
internal string GetParts(UriComponents uriParts, UriFormat formatAs)
{
- return GetComponents(uriParts, formatAs);
+ return InternalGetComponents(uriParts, formatAs);
}
private string GetEscapedParts(UriComponents uriParts)
@@ -3158,9 +3185,6 @@ private unsafe void ParseRemaining()
idx = _info.Offset.Path;
origIdx = _info.Offset.Path;
- //Some uris do not have a query
- // When '?' is passed as delimiter, then it's special case
- // so both '?' and '#' will work as delimiters
if (buildIriStringFromPath)
{
DebugAssertInCtor();
@@ -3180,6 +3204,45 @@ private unsafe void ParseRemaining()
_info.Offset.Path = (ushort)_string.Length;
idx = _info.Offset.Path;
+ }
+
+ // If the user explicitly disabled canonicalization, only figure out the offsets
+ if (DisablePathAndQueryCanonicalization)
+ {
+ if (buildIriStringFromPath)
+ {
+ DebugAssertInCtor();
+ _string += _originalUnicodeString.Substring(origIdx);
+ }
+
+ string str = _string;
+
+ if (IsImplicitFile || (syntaxFlags & UriSyntaxFlags.MayHaveQuery) == 0)
+ {
+ idx = str.Length;
+ }
+ else
+ {
+ idx = str.IndexOf('?');
+ if (idx == -1)
+ {
+ idx = str.Length;
+ }
+ }
+
+ _info.Offset.Query = (ushort)idx;
+ _info.Offset.Fragment = (ushort)str.Length; // There is no fragment in UseRawTarget mode
+ _info.Offset.End = (ushort)str.Length;
+
+ goto Done;
+ }
+
+ //Some uris do not have a query
+ // When '?' is passed as delimiter, then it's special case
+ // so both '?' and '#' will work as delimiters
+ if (buildIriStringFromPath)
+ {
+ DebugAssertInCtor();
int offset = origIdx;
if (IsImplicitFile || ((syntaxFlags & (UriSyntaxFlags.MayHaveQuery | UriSyntaxFlags.MayHaveFragment)) == 0))
diff --git a/src/libraries/System.Private.Uri/src/System/UriCreationOptions.cs b/src/libraries/System.Private.Uri/src/System/UriCreationOptions.cs
new file mode 100644
index 00000000000000..2d0ee84d08b218
--- /dev/null
+++ b/src/libraries/System.Private.Uri/src/System/UriCreationOptions.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System
+{
+ ///
+ /// Options that control how a is created and behaves.
+ ///
+ public struct UriCreationOptions
+ {
+ private bool _disablePathAndQueryCanonicalization;
+
+ ///
+ /// Disables validation and normalization of the Path and Query.
+ /// No transformations of the URI past the Authority will take place.
+ /// instances created with this option do not support s.
+ /// may not be used for or .
+ /// Be aware that disabling canonicalization also means that reserved characters will not be escaped,
+ /// which may corrupt the HTTP request and makes the application subject to request smuggling.
+ /// Only set this option if you have ensured that the URI string is already sanitized.
+ ///
+ public bool DangerousDisablePathAndQueryCanonicalization
+ {
+ readonly get => _disablePathAndQueryCanonicalization;
+ set => _disablePathAndQueryCanonicalization = value;
+ }
+ }
+}
diff --git a/src/libraries/System.Private.Uri/src/System/UriExt.cs b/src/libraries/System.Private.Uri/src/System/UriExt.cs
index a644dfa566699a..070e11a7f987f3 100644
--- a/src/libraries/System.Private.Uri/src/System/UriExt.cs
+++ b/src/libraries/System.Private.Uri/src/System/UriExt.cs
@@ -13,7 +13,7 @@ public partial class Uri
//
// All public ctors go through here
//
- private void CreateThis(string? uri, bool dontEscape, UriKind uriKind)
+ private void CreateThis(string? uri, bool dontEscape, UriKind uriKind, in UriCreationOptions creationOptions = default)
{
DebugAssertInCtor();
@@ -31,6 +31,9 @@ private void CreateThis(string? uri, bool dontEscape, UriKind uriKind)
if (dontEscape)
_flags |= Flags.UserEscaped;
+ if (creationOptions.DangerousDisablePathAndQueryCanonicalization)
+ _flags |= Flags.DisablePathAndQueryCanonicalization;
+
ParsingError err = ParseScheme(_string, ref _flags, ref _syntax!);
InitializeUri(err, uriKind, out UriFormatException? e);
@@ -259,6 +262,26 @@ public static bool TryCreate([NotNullWhen(true)] string? uriString, UriKind uriK
return e is null && result != null;
}
+ ///
+ /// Creates a new using the specified instance and .
+ ///
+ /// The string representation of the .
+ /// Options that control how the is created and behaves.
+ /// The constructed .
+ /// if the was successfully created; otherwise, .
+ public static bool TryCreate([NotNullWhen(true)] string? uriString, in UriCreationOptions creationOptions, [NotNullWhen(true)] out Uri? result)
+ {
+ if (uriString is null)
+ {
+ result = null;
+ return false;
+ }
+ UriFormatException? e = null;
+ result = CreateHelper(uriString, false, UriKind.Absolute, ref e, in creationOptions);
+ result?.DebugSetLeftCtor();
+ return e is null && result != null;
+ }
+
public static bool TryCreate(Uri? baseUri, string? relativeUri, [NotNullWhen(true)] out Uri? result)
{
if (TryCreate(relativeUri, UriKind.RelativeOrAbsolute, out Uri? relativeLink))
@@ -309,6 +332,16 @@ public static bool TryCreate(Uri? baseUri, Uri? relativeUri, [NotNullWhen(true)]
}
public string GetComponents(UriComponents components, UriFormat format)
+ {
+ if (DisablePathAndQueryCanonicalization && (components & (UriComponents.Path | UriComponents.Query)) != 0)
+ {
+ throw new InvalidOperationException(SR.net_uri_GetComponentsCalledWhenCanonicalizationDisabled);
+ }
+
+ return InternalGetComponents(components, format);
+ }
+
+ private string InternalGetComponents(UriComponents components, UriFormat format)
{
if (((components & UriComponents.SerializationInfoString) != 0) && components != UriComponents.SerializationInfoString)
throw new ArgumentOutOfRangeException(nameof(components), components, SR.net_uri_NotJustSerialization);
@@ -590,7 +623,7 @@ private Uri(Flags flags, UriParser? uriParser, string uri)
//
// a Uri.TryCreate() method goes through here.
//
- internal static Uri? CreateHelper(string uriString, bool dontEscape, UriKind uriKind, ref UriFormatException? e)
+ internal static Uri? CreateHelper(string uriString, bool dontEscape, UriKind uriKind, ref UriFormatException? e, in UriCreationOptions creationOptions = default)
{
// if (!Enum.IsDefined(typeof(UriKind), uriKind)) -- We currently believe that Enum.IsDefined() is too slow
// to be used here.
@@ -606,6 +639,9 @@ private Uri(Flags flags, UriParser? uriParser, string uri)
if (dontEscape)
flags |= Flags.UserEscaped;
+ if (creationOptions.DangerousDisablePathAndQueryCanonicalization)
+ flags |= Flags.DisablePathAndQueryCanonicalization;
+
// We won't use User factory for these errors
if (err != ParsingError.None)
{
diff --git a/src/libraries/System.Private.Uri/src/System/UriScheme.cs b/src/libraries/System.Private.Uri/src/System/UriScheme.cs
index d9d96ab59ea3cb..7c39a6c44a336e 100644
--- a/src/libraries/System.Private.Uri/src/System/UriScheme.cs
+++ b/src/libraries/System.Private.Uri/src/System/UriScheme.cs
@@ -146,6 +146,9 @@ protected virtual string GetComponents(Uri uri, UriComponents components, UriFor
if (!uri.IsAbsoluteUri)
throw new InvalidOperationException(SR.net_uri_NotAbsolute);
+ if (uri.DisablePathAndQueryCanonicalization && (components & (UriComponents.Path | UriComponents.Query)) != 0)
+ throw new InvalidOperationException(SR.net_uri_GetComponentsCalledWhenCanonicalizationDisabled);
+
return uri.GetComponentsHelper(components, format);
}
diff --git a/src/libraries/System.Private.Uri/tests/FunctionalTests/System.Private.Uri.Functional.Tests.csproj b/src/libraries/System.Private.Uri/tests/FunctionalTests/System.Private.Uri.Functional.Tests.csproj
index 8f07bb90af1ffe..21bb5200471aa1 100644
--- a/src/libraries/System.Private.Uri/tests/FunctionalTests/System.Private.Uri.Functional.Tests.csproj
+++ b/src/libraries/System.Private.Uri/tests/FunctionalTests/System.Private.Uri.Functional.Tests.csproj
@@ -17,6 +17,7 @@
+
diff --git a/src/libraries/System.Private.Uri/tests/FunctionalTests/UriCreationOptionsTest.cs b/src/libraries/System.Private.Uri/tests/FunctionalTests/UriCreationOptionsTest.cs
new file mode 100644
index 00000000000000..3f7438738f0bf9
--- /dev/null
+++ b/src/libraries/System.Private.Uri/tests/FunctionalTests/UriCreationOptionsTest.cs
@@ -0,0 +1,294 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+using System.Linq;
+using Xunit;
+
+namespace System.PrivateUri.Tests
+{
+ public class UriCreationOptionsTest
+ {
+ [Fact]
+ public void UriCreationOptions_HasReasonableDefaults()
+ {
+ UriCreationOptions options = default;
+
+ Assert.False(options.DangerousDisablePathAndQueryCanonicalization);
+ }
+
+ [Fact]
+ public void UriCreationOptions_StoresCorrectValues()
+ {
+ var options = new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = true };
+ Assert.True(options.DangerousDisablePathAndQueryCanonicalization);
+
+ options = new UriCreationOptions { DangerousDisablePathAndQueryCanonicalization = false };
+ Assert.False(options.DangerousDisablePathAndQueryCanonicalization);
+ }
+
+ public static IEnumerable