diff --git a/.azure/pipelines/identitymodel-helix-matrix.yml b/.azure/pipelines/identitymodel-helix-matrix.yml
index 91be7f22c42f..d0002c3b1f15 100644
--- a/.azure/pipelines/identitymodel-helix-matrix.yml
+++ b/.azure/pipelines/identitymodel-helix-matrix.yml
@@ -24,7 +24,7 @@ resources:
ref: refs/tags/release
extends:
- template: v1/1ES.Official.PipelineTemplate.yml@1esPipelines
+ template: v1/1ES.Unofficial.PipelineTemplate.yml@1esPipelines
parameters:
sdl:
sourceAnalysisPool:
diff --git a/NuGet.config b/NuGet.config
index 05d6d50db75d..6f6f3bfde211 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -6,10 +6,10 @@
-
+
-
+
@@ -30,10 +30,10 @@
-
+
-
+
diff --git a/eng/Baseline.Designer.props b/eng/Baseline.Designer.props
index af8b9b06b329..d622c72bd232 100644
--- a/eng/Baseline.Designer.props
+++ b/eng/Baseline.Designer.props
@@ -2,117 +2,117 @@
$(MSBuildAllProjects);$(MSBuildThisFileFullPath)
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
-
+
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
@@ -120,138 +120,138 @@
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
-
+
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
-
+
- 8.0.19
+ 8.0.20
-
-
+
+
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
-
-
+
+
- 8.0.19
+ 8.0.20
-
+
- 8.0.19
+ 8.0.20
-
+
- 8.0.19
+ 8.0.20
-
+
- 8.0.19
+ 8.0.20
-
-
+
+
- 8.0.19
+ 8.0.20
-
-
-
+
+
+
- 8.0.19
+ 8.0.20
-
-
+
+
- 8.0.19
+ 8.0.20
-
-
+
+
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
-
-
+
+
@@ -259,7 +259,7 @@
- 8.0.19
+ 8.0.20
@@ -268,51 +268,51 @@
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
-
-
+
+
@@ -322,8 +322,8 @@
-
-
+
+
@@ -331,8 +331,8 @@
-
-
+
+
@@ -343,58 +343,58 @@
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
-
-
+
+
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
-
+
- 8.0.19
+ 8.0.20
@@ -403,7 +403,7 @@
- 8.0.19
+ 8.0.20
@@ -411,71 +411,71 @@
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
-
-
+
+
- 8.0.19
+ 8.0.20
-
-
+
+
- 8.0.19
+ 8.0.20
@@ -491,27 +491,27 @@
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
-
+
- 8.0.19
+ 8.0.20
@@ -520,23 +520,23 @@
- 8.0.19
+ 8.0.20
-
+
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
@@ -545,54 +545,54 @@
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
-
-
+
+
-
-
+
+
-
-
+
+
- 8.0.19
+ 8.0.20
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
@@ -600,83 +600,83 @@
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
-
-
-
-
+
+
+
+
- 8.0.19
+ 8.0.20
@@ -685,64 +685,64 @@
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
-
+
- 8.0.19
+ 8.0.20
-
+
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
@@ -764,7 +764,7 @@
- 8.0.19
+ 8.0.20
@@ -786,7 +786,7 @@
- 8.0.19
+ 8.0.20
@@ -802,23 +802,23 @@
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
@@ -826,24 +826,24 @@
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
-
-
-
+
+
+
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
@@ -853,7 +853,7 @@
- 8.0.19
+ 8.0.20
@@ -862,73 +862,73 @@
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
-
+
-
+
-
+
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
@@ -957,11 +957,11 @@
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
@@ -979,18 +979,18 @@
- 8.0.19
+ 8.0.20
- 8.0.19
+ 8.0.20
-
+
- 8.0.19
+ 8.0.20
diff --git a/eng/Baseline.xml b/eng/Baseline.xml
index 5e40f13f2eca..86b656657f27 100644
--- a/eng/Baseline.xml
+++ b/eng/Baseline.xml
@@ -4,110 +4,110 @@ This file contains a list of all the packages and their versions which were rele
Update this list when preparing for a new patch.
-->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/eng/SourceBuildPrebuiltBaseline.xml b/eng/SourceBuildPrebuiltBaseline.xml
index dda41055550d..f92cf6f96b1b 100644
--- a/eng/SourceBuildPrebuiltBaseline.xml
+++ b/eng/SourceBuildPrebuiltBaseline.xml
@@ -42,5 +42,12 @@
+
+
+
+
+
+
+
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 346a9afd7c06..363bcf5399d6 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -9,37 +9,37 @@
-->
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- a947fe22902f3f0b921f5dafed9f059eaa4d18c6
+ bd381fa6af1f80b3b6a52739729596cd68b6f5c8
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- a947fe22902f3f0b921f5dafed9f059eaa4d18c6
+ bd381fa6af1f80b3b6a52739729596cd68b6f5c8
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- a947fe22902f3f0b921f5dafed9f059eaa4d18c6
+ bd381fa6af1f80b3b6a52739729596cd68b6f5c8
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- a947fe22902f3f0b921f5dafed9f059eaa4d18c6
+ bd381fa6af1f80b3b6a52739729596cd68b6f5c8
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- a947fe22902f3f0b921f5dafed9f059eaa4d18c6
+ bd381fa6af1f80b3b6a52739729596cd68b6f5c8
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- a947fe22902f3f0b921f5dafed9f059eaa4d18c6
+ bd381fa6af1f80b3b6a52739729596cd68b6f5c8
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- a947fe22902f3f0b921f5dafed9f059eaa4d18c6
+ bd381fa6af1f80b3b6a52739729596cd68b6f5c8
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-efcore
- a947fe22902f3f0b921f5dafed9f059eaa4d18c6
+ bd381fa6af1f80b3b6a52739729596cd68b6f5c8
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
@@ -121,9 +121,9 @@
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
5535e31a712343a63f5d7d796cd874e563e5ac14
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 574100b692e71fa3426931adf4c1ba42e4ee5213
+ 362ab6669d55a75d51166f01b596c967c734ef4c
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
@@ -185,9 +185,9 @@
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
5535e31a712343a63f5d7d796cd874e563e5ac14
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 574100b692e71fa3426931adf4c1ba42e4ee5213
+ 362ab6669d55a75d51166f01b596c967c734ef4c
https://github.com/dotnet/source-build-externals
@@ -275,17 +275,17 @@
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
81cabf2857a01351e5ab578947c7403a5b128ad1
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 574100b692e71fa3426931adf4c1ba42e4ee5213
+ 362ab6669d55a75d51166f01b596c967c734ef4c
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 574100b692e71fa3426931adf4c1ba42e4ee5213
+ 362ab6669d55a75d51166f01b596c967c734ef4c
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 574100b692e71fa3426931adf4c1ba42e4ee5213
+ 362ab6669d55a75d51166f01b596c967c734ef4c
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
@@ -316,31 +316,31 @@
Win-x64 is used here because we have picked an arbitrary runtime identifier to flow the version of the latest NETCore.App runtime.
All Runtime.$rid packages should have the same version.
-->
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 574100b692e71fa3426931adf4c1ba42e4ee5213
+ 362ab6669d55a75d51166f01b596c967c734ef4c
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 574100b692e71fa3426931adf4c1ba42e4ee5213
+ 362ab6669d55a75d51166f01b596c967c734ef4c
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 574100b692e71fa3426931adf4c1ba42e4ee5213
+ 362ab6669d55a75d51166f01b596c967c734ef4c
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 574100b692e71fa3426931adf4c1ba42e4ee5213
+ 362ab6669d55a75d51166f01b596c967c734ef4c
https://github.com/dotnet/xdt
9a1c3e1b7f0c8763d4c96e593961a61a72679a7b
-
+
https://github.com/dotnet/source-build-reference-packages
- 3827e68e002064268d4be4b2d1d96048f9794808
+ 0b4984f8ee945e02a39ef0f72dc9f7ceab65c14f
@@ -368,9 +368,9 @@
-
+
https://dev.azure.com/dnceng/internal/_git/dotnet-runtime
- 574100b692e71fa3426931adf4c1ba42e4ee5213
+ 362ab6669d55a75d51166f01b596c967c734ef4c
https://github.com/dotnet/winforms
diff --git a/eng/Versions.props b/eng/Versions.props
index dfc636c88f04..5168af8df055 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -8,7 +8,7 @@
8
0
- 20
+ 21
true
@@ -67,12 +67,12 @@
8.0.2
- 8.0.20
- 8.0.20
- 8.0.20
- 8.0.20
- 8.0.20
- 8.0.20-servicing.25419.14
+ 8.0.21
+ 8.0.21
+ 8.0.21
+ 8.0.21
+ 8.0.21
+ 8.0.21-servicing.25475.13
8.0.0
8.0.1
8.0.0
@@ -93,7 +93,7 @@
8.0.0
8.0.0
8.0.0
- 8.0.20-servicing.25419.14
+ 8.0.21-servicing.25475.13
8.0.1
8.0.1
8.0.1
@@ -109,7 +109,7 @@
8.0.0
8.0.2
8.0.0
- 8.0.20-servicing.25419.14
+ 8.0.21-servicing.25475.13
8.0.1
8.0.1
8.0.2
@@ -129,9 +129,9 @@
8.0.0
8.0.0
8.0.0
- 8.0.20-servicing.25419.14
+ 8.0.21-servicing.25475.13
- 8.0.20-servicing.25419.14
+ 8.0.21-servicing.25475.13
8.0.0
8.0.1
@@ -143,14 +143,14 @@
9.0.0-preview.9.24518.1
9.0.0-preview.9.24518.1
- 8.0.20
- 8.0.20
- 8.0.20
- 8.0.20
- 8.0.20
- 8.0.20
- 8.0.20
- 8.0.20
+ 8.0.21
+ 8.0.21
+ 8.0.21
+ 8.0.21
+ 8.0.21
+ 8.0.21
+ 8.0.21
+ 8.0.21
4.8.0-7.24574.2
4.8.0-7.24574.2
@@ -168,7 +168,7 @@
8.0.0-alpha.1.25202.2
- 8.0.0-alpha.1.25316.2
+ 8.0.0-alpha.1.25428.6
2.0.0-beta-23228-03
@@ -198,8 +198,6 @@
5.0.0-preview.3.20215.2
15.9.3032
-
- 6.0.1
$(SystemTextJsonVersion)
4.7.0
@@ -223,13 +221,12 @@
6.0.0
1.1.1
- 17.4.0
+ 17.8.29
1.2.0
- 17.4.0
- 17.4.0
- 17.4.0
+ 17.8.29
+ 17.8.29
+ 17.8.29
1.2.6
- 17.4.0
-
diff --git a/global.json b/global.json
index eb59ddf5a90c..85dca8c801cd 100644
--- a/global.json
+++ b/global.json
@@ -1,9 +1,9 @@
{
"sdk": {
- "version": "8.0.119"
+ "version": "8.0.120"
},
"tools": {
- "dotnet": "8.0.119",
+ "dotnet": "8.0.120",
"runtimes": {
"dotnet/x86": [
"$(MicrosoftNETCoreBrowserDebugHostTransportVersion)"
diff --git a/src/Components/test/E2ETest/ServerRenderingTests/EnhancedNavigationTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/EnhancedNavigationTest.cs
index 158cc2d42c8d..8f47410c5fb1 100644
--- a/src/Components/test/E2ETest/ServerRenderingTests/EnhancedNavigationTest.cs
+++ b/src/Components/test/E2ETest/ServerRenderingTests/EnhancedNavigationTest.cs
@@ -526,13 +526,21 @@ public void NavigationManagerUriGetsUpdatedOnEnhancedNavigation_BothServerAndWeb
Browser.Exists(By.TagName("nav")).FindElement(By.LinkText("LocationChanged/LocationChanging event (server-and-wasm)")).Click();
Browser.Equal("Page with location changed components", () => Browser.Exists(By.TagName("h1")).Text);
- Assert.EndsWith("/nav/location-changed/server-and-wasm", Browser.Exists(By.Id("nav-uri-server")).Text);
- Assert.EndsWith("/nav/location-changed/server-and-wasm", Browser.Exists(By.Id("nav-uri-wasm")).Text);
+ Browser.True(() => Browser.Exists(By.Id("nav-uri-server")).Text.EndsWith(
+ "/nav/location-changed/server-and-wasm",
+ StringComparison.Ordinal));
+ Browser.True(() => Browser.Exists(By.Id("nav-uri-wasm")).Text.EndsWith(
+ "/nav/location-changed/server-and-wasm",
+ StringComparison.Ordinal));
Browser.Exists(By.Id($"update-query-string-{runtimeThatInvokedNavigation}")).Click();
- Assert.EndsWith($"/nav/location-changed/server-and-wasm?query=1", Browser.Exists(By.Id($"nav-uri-server")).Text);
- Assert.EndsWith($"/nav/location-changed/server-and-wasm?query=1", Browser.Exists(By.Id($"nav-uri-wasm")).Text);
+ Browser.True(() => Browser.Exists(By.Id("nav-uri-server")).Text.EndsWith(
+ "/nav/location-changed/server-and-wasm?query=1",
+ StringComparison.Ordinal));
+ Browser.True(() => Browser.Exists(By.Id("nav-uri-wasm")).Text.EndsWith(
+ "/nav/location-changed/server-and-wasm?query=1",
+ StringComparison.Ordinal));
}
[Theory]
diff --git a/src/Components/test/E2ETest/ServerRenderingTests/FormHandlingTests/FormWithParentBindingContextTest.cs b/src/Components/test/E2ETest/ServerRenderingTests/FormHandlingTests/FormWithParentBindingContextTest.cs
index b8171c827e41..3b27216b5042 100644
--- a/src/Components/test/E2ETest/ServerRenderingTests/FormHandlingTests/FormWithParentBindingContextTest.cs
+++ b/src/Components/test/E2ETest/ServerRenderingTests/FormHandlingTests/FormWithParentBindingContextTest.cs
@@ -1344,19 +1344,19 @@ public void RadioButtonGetsResetAfterSubmittingEnhancedForm()
{
GoTo("forms/form-with-checkbox-and-radio-button");
- Assert.False(Browser.Exists(By.Id("checkbox")).Selected);
- Assert.False(Browser.Exists(By.Id("radio-button")).Selected);
+ WaitAssert.False(Browser, () => Browser.Exists(By.Id("checkbox")).Selected);
+ WaitAssert.False(Browser, () => Browser.Exists(By.Id("radio-button")).Selected);
Browser.Exists(By.Id("checkbox")).Click();
Browser.Exists(By.Id("radio-button")).Click();
- Assert.True(Browser.Exists(By.Id("checkbox")).Selected);
- Assert.True(Browser.Exists(By.Id("radio-button")).Selected);
+ WaitAssert.True(Browser, () => Browser.Exists(By.Id("checkbox")).Selected);
+ WaitAssert.True(Browser, () => Browser.Exists(By.Id("radio-button")).Selected);
Browser.Exists(By.Id("submit-button")).Click();
- Assert.False(Browser.Exists(By.Id("checkbox")).Selected);
- Assert.False(Browser.Exists(By.Id("radio-button")).Selected);
+ WaitAssert.False(Browser, () => Browser.Exists(By.Id("checkbox")).Selected);
+ WaitAssert.False(Browser, () => Browser.Exists(By.Id("radio-button")).Selected);
}
[Fact]
diff --git a/src/Installers/Debian/Directory.Build.targets b/src/Installers/Debian/Directory.Build.targets
index 2d854470f156..771ecec7da73 100644
--- a/src/Installers/Debian/Directory.Build.targets
+++ b/src/Installers/Debian/Directory.Build.targets
@@ -60,5 +60,6 @@
+
diff --git a/src/Installers/Debian/Runtime/Debian.Runtime.debproj b/src/Installers/Debian/Runtime/Debian.Runtime.debproj
index 343216335618..85391faafac4 100644
--- a/src/Installers/Debian/Runtime/Debian.Runtime.debproj
+++ b/src/Installers/Debian/Runtime/Debian.Runtime.debproj
@@ -34,6 +34,7 @@
$(RuntimeInstallerBaseName)-$(SharedFxVersion)-x64.deb
+ $(RuntimeInstallerBaseName)-$(SharedFxVersion)-newkey-x64.deb
$(TargetDir)$(TargetFileName)
$(VersionPrefix)
diff --git a/src/Installers/Debian/TargetingPack/Debian.TargetingPack.debproj b/src/Installers/Debian/TargetingPack/Debian.TargetingPack.debproj
index 5295906837c5..4ffc3aa85fe8 100644
--- a/src/Installers/Debian/TargetingPack/Debian.TargetingPack.debproj
+++ b/src/Installers/Debian/TargetingPack/Debian.TargetingPack.debproj
@@ -38,6 +38,7 @@
$(TargetingPackInstallerBaseName)-$(TargetingPackVersion)-$(TargetArchitecture).deb
+ $(TargetingPackInstallerBaseName)-$(TargetingPackVersion)-newkey-$(TargetArchitecture).deb
$(TargetDir)$(TargetFileName)
$(TargetingPackVersionPrefix)
diff --git a/src/Installers/Rpm/Directory.Build.props b/src/Installers/Rpm/Directory.Build.props
index b436fc469b10..390975f93156 100644
--- a/src/Installers/Rpm/Directory.Build.props
+++ b/src/Installers/Rpm/Directory.Build.props
@@ -11,6 +11,7 @@
-cm.1
-cm.2
+ -newkey
true
diff --git a/src/Installers/Rpm/Directory.Build.targets b/src/Installers/Rpm/Directory.Build.targets
index 30d705abb1dc..e9800cf062eb 100644
--- a/src/Installers/Rpm/Directory.Build.targets
+++ b/src/Installers/Rpm/Directory.Build.targets
@@ -40,6 +40,7 @@
$(InstallersOutputPath)$(CblMarinerBaseName)$(CblMariner1VersionSuffix)$(CblMarinerExtension)
$(InstallersOutputPath)$(CblMarinerBaseName)$(CblMariner2VersionSuffix)$(CblMarinerExtension)
+ $(InstallersOutputPath)$(NewKeyBaseName)$(NewKeyVersionSuffix)$(NewKeyExtension)
@@ -103,5 +104,13 @@
UseHardlinksIfPossible="False" />
+
+
+
+
diff --git a/src/Installers/Rpm/Runtime/Rpm.Runtime.rpmproj b/src/Installers/Rpm/Runtime/Rpm.Runtime.rpmproj
index 5e0427aea7f8..26e74893aba8 100644
--- a/src/Installers/Rpm/Runtime/Rpm.Runtime.rpmproj
+++ b/src/Installers/Rpm/Runtime/Rpm.Runtime.rpmproj
@@ -16,5 +16,7 @@
$(InstallersOutputPath)$(TargetFileName)
$(RuntimeInstallerBaseName)-$(SharedFxVersion)
-$(RpmArch).rpm
+ $(RuntimeInstallerBaseName)-$(SharedFxVersion)
+ -$(RpmArch).rpm
diff --git a/src/Installers/Rpm/TargetingPack/Rpm.TargetingPack.rpmproj b/src/Installers/Rpm/TargetingPack/Rpm.TargetingPack.rpmproj
index a29db936bd79..7098eaea452c 100644
--- a/src/Installers/Rpm/TargetingPack/Rpm.TargetingPack.rpmproj
+++ b/src/Installers/Rpm/TargetingPack/Rpm.TargetingPack.rpmproj
@@ -33,6 +33,8 @@
$(InstallersOutputPath)$(TargetFileName)
$(TargetingPackInstallerBaseName)-$(TargetingPackVersion)
-$(RpmArch).rpm
+ $(TargetingPackInstallerBaseName)-$(TargetingPackVersion)
+ -$(RpmArch).rpm
$(TargetingPackVersionPrefix)
diff --git a/src/Servers/HttpSys/test/FunctionalTests/ResponseBodyTests.cs b/src/Servers/HttpSys/test/FunctionalTests/ResponseBodyTests.cs
index 0f442b7fd36d..1c504efc57c0 100644
--- a/src/Servers/HttpSys/test/FunctionalTests/ResponseBodyTests.cs
+++ b/src/Servers/HttpSys/test/FunctionalTests/ResponseBodyTests.cs
@@ -206,6 +206,7 @@ public async Task ResponseBody_WriteChunked_ManuallyChunked()
}
[ConditionalFact]
+ [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/63532")]
public async Task ResponseBody_WriteContentLength_PassedThrough()
{
string address;
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.cpp b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.cpp
index 7096cf85b808..f1f3fe7afcbf 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.cpp
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.cpp
@@ -133,6 +133,23 @@ std::wstring Environment::GetDllDirectoryValue()
return expandedStr;
}
+ProcessorArchitecture Environment::GetCurrentProcessArchitecture()
+{
+ // Use compile-time detection - we know which architectures we support
+ // and this is the most reliable and efficient approach. IsWow64Process2
+ // doesn't show the correct architecture when running under x64 emulation
+ // on ARM64.
+#if defined(_M_ARM64)
+ return ProcessorArchitecture::ARM64;
+#elif defined(_M_AMD64)
+ return ProcessorArchitecture::AMD64;
+#elif defined(_M_IX86)
+ return ProcessorArchitecture::x86;
+#else
+ static_assert(false, "Unknown target architecture");
+#endif
+}
+
bool Environment::IsRunning64BitProcess()
{
// Check the bitness of the currently running process
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.h
index 9e3e1b1bf772..a9e6e85d9ecc 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.h
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/Environment.h
@@ -5,6 +5,7 @@
#include
#include
+#include "ProcessorArchitecture.h"
class Environment
{
@@ -23,6 +24,8 @@ class Environment
static
bool IsRunning64BitProcess();
static
+ ProcessorArchitecture GetCurrentProcessArchitecture();
+ static
HRESULT CopyToDirectory(const std::wstring& source, const std::filesystem::path& destination, bool cleanDest, const std::filesystem::path& directoryToIgnore, int& copiedFileCount);
static
bool CheckUpToDate(const std::wstring& source, const std::filesystem::path& destination, const std::wstring& extension, const std::filesystem::path& directoryToIgnore);
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.cpp b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.cpp
index 8fb960261590..8552852ce0e5 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.cpp
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.cpp
@@ -409,10 +409,9 @@ HostFxrResolver::InvokeWhereToFindDotnet()
HandleWrapper hStdOutWritePipe;
HandleWrapper hProcess;
HandleWrapper hThread;
- CComBSTR pwzDotnetName = NULL;
- DWORD dwFilePointer;
- BOOL fIsCurrentProcess64Bit;
- DWORD dwExitCode;
+ CComBSTR pwzDotnetName = nullptr;
+ DWORD dwFilePointer = 0;
+ DWORD dwExitCode = 0;
STRU struDotnetSubstring;
STRU struDotnetLocationsString;
DWORD dwNumBytesRead = 0;
@@ -426,6 +425,7 @@ HostFxrResolver::InvokeWhereToFindDotnet()
securityAttributes.bInheritHandle = TRUE;
LOG_INFO(L"Invoking where.exe to find dotnet.exe");
+ auto currentProcessArch = Environment::GetCurrentProcessArchitecture();
// Create a read/write pipe that will be used for reading the result of where.exe
FINISHED_LAST_ERROR_IF(!CreatePipe(&hStdOutReadPipe, &hStdOutWritePipe, &securityAttributes, 0));
@@ -499,13 +499,9 @@ HostFxrResolver::InvokeWhereToFindDotnet()
}
FINISHED_IF_FAILED(struDotnetLocationsString.CopyA(pzFileContents, dwNumBytesRead));
-
LOG_INFOF(L"where.exe invocation returned: '%ls'", struDotnetLocationsString.QueryStr());
- fIsCurrentProcess64Bit = Environment::IsRunning64BitProcess();
-
- LOG_INFOF(L"Current process bitness type detected as isX64=%d", fIsCurrentProcess64Bit);
-
+ // Look for a dotnet.exe that matches the current process architecture
while (TRUE)
{
index = struDotnetLocationsString.IndexOf(L"\r\n", prevIndex);
@@ -518,28 +514,38 @@ HostFxrResolver::InvokeWhereToFindDotnet()
// \r\n is two wchars, so add 2 here.
prevIndex = index + 2;
- LOG_INFOF(L"Processing entry '%ls'", struDotnetSubstring.QueryStr());
-
- if (fIsCurrentProcess64Bit == IsX64(struDotnetSubstring.QueryStr()))
+ ProcessorArchitecture dotnetArch = GetFileProcessorArchitecture(struDotnetSubstring.QueryStr());
+ if (dotnetArch == currentProcessArch)
{
- // The bitness of dotnet matched with the current worker process bitness.
+ LOG_INFOF(L"Found dotnet.exe matching current process architecture (%ls) '%ls'",
+ ProcessorArchitectureToString(dotnetArch),
+ struDotnetSubstring.QueryStr());
+
return std::make_optional(struDotnetSubstring.QueryStr());
}
+ else
+ {
+ LOG_INFOF(L"Skipping dotnet.exe with non-matching architecture %ls (need %ls). '%ls'",
+ ProcessorArchitectureToString(dotnetArch),
+ ProcessorArchitectureToString(currentProcessArch),
+ struDotnetSubstring.QueryStr());
+ }
}
Finished:
return result;
}
-BOOL HostFxrResolver::IsX64(const WCHAR* dotnetPath)
+// Reads the PE header of the binary to determine its architecture.
+ProcessorArchitecture HostFxrResolver::GetFileProcessorArchitecture(const WCHAR* binaryPath)
{
// Errors while reading from the file shouldn't throw unless
// file.exception(bits) is set
- std::ifstream file(dotnetPath, std::ios::binary);
+ std::ifstream file(binaryPath, std::ios::binary);
if (!file.is_open())
{
- LOG_TRACEF(L"Failed to open file %ls", dotnetPath);
- return false;
+ LOG_TRACEF(L"Failed to open file %ls", binaryPath);
+ return ProcessorArchitecture::Unknown;
}
// Read the DOS header
@@ -547,8 +553,8 @@ BOOL HostFxrResolver::IsX64(const WCHAR* dotnetPath)
file.read(reinterpret_cast(&dosHeader), sizeof(dosHeader));
if (dosHeader.e_magic != IMAGE_DOS_SIGNATURE) // 'MZ'
{
- LOG_TRACEF(L"%ls is not a valid executable file (missing MZ header).", dotnetPath);
- return false;
+ LOG_TRACEF(L"%ls is not a valid executable file (missing MZ header).", binaryPath);
+ return ProcessorArchitecture::Unknown;
}
// Seek to the PE header
@@ -559,32 +565,30 @@ BOOL HostFxrResolver::IsX64(const WCHAR* dotnetPath)
file.read(reinterpret_cast(&peSignature), sizeof(peSignature));
if (peSignature != IMAGE_NT_SIGNATURE) // 'PE\0\0'
{
- LOG_TRACEF(L"%ls is not a valid PE file (missing PE header).", dotnetPath);
- return false;
+ LOG_TRACEF(L"%ls is not a valid PE file (missing PE header).", binaryPath);
+ return ProcessorArchitecture::Unknown;
}
// Read the file header
IMAGE_FILE_HEADER fileHeader{};
file.read(reinterpret_cast(&fileHeader), sizeof(fileHeader));
- // Read the optional header magic field
- WORD magic{};
- file.read(reinterpret_cast(&magic), sizeof(magic));
-
- // Determine the architecture based on the magic value
- if (magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+ // Determine the architecture based on the machine type
+ switch (fileHeader.Machine)
{
- LOG_INFOF(L"%ls is 32-bit", dotnetPath);
- return false;
- }
- else if (magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
- {
- LOG_INFOF(L"%ls is 64-bit", dotnetPath);
- return true;
+ case IMAGE_FILE_MACHINE_I386:
+ LOG_INFOF(L"%ls is x86 (32-bit)", binaryPath);
+ return ProcessorArchitecture::x86;
+ case IMAGE_FILE_MACHINE_AMD64:
+ LOG_INFOF(L"%ls is AMD64 (x64)", binaryPath);
+ return ProcessorArchitecture::AMD64;
+ case IMAGE_FILE_MACHINE_ARM64:
+ LOG_INFOF(L"%ls is ARM64", binaryPath);
+ return ProcessorArchitecture::ARM64;
+ default:
+ LOG_INFOF(L"%ls has unknown architecture (machine type: 0x%X)", binaryPath, fileHeader.Machine);
+ return ProcessorArchitecture::Unknown;
}
-
- LOG_INFOF(L"%ls is unknown architecture %i", dotnetPath, fileHeader.Machine);
- return false;
}
std::optional
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.h
index 08ec650aec54..9065e2aecd2b 100644
--- a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.h
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/HostFxrResolver.h
@@ -8,8 +8,8 @@
#include
#include
#include
-
#include "ErrorContext.h"
+#include "ProcessorArchitecture.h"
#define READ_BUFFER_SIZE 4096
@@ -74,7 +74,7 @@ class HostFxrResolver
const std::filesystem::path & requestedPath
);
- static BOOL IsX64(const WCHAR* dotnetPath);
+ static ProcessorArchitecture GetFileProcessorArchitecture(const WCHAR* binaryPath);
struct LocalFreeDeleter
{
diff --git a/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ProcessorArchitecture.h b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ProcessorArchitecture.h
new file mode 100644
index 000000000000..195feddcae7b
--- /dev/null
+++ b/src/Servers/IIS/AspNetCoreModuleV2/CommonLib/ProcessorArchitecture.h
@@ -0,0 +1,28 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the MIT License. See License.txt in the project root for license information.
+
+#pragma once
+
+enum class ProcessorArchitecture
+{
+ Unknown,
+ x86,
+ AMD64,
+ ARM64
+};
+
+inline const wchar_t* ProcessorArchitectureToString(ProcessorArchitecture arch)
+{
+ switch (arch)
+ {
+ case ProcessorArchitecture::x86:
+ return L"x86";
+ case ProcessorArchitecture::AMD64:
+ return L"AMD64";
+ case ProcessorArchitecture::ARM64:
+ return L"ARM64";
+ case ProcessorArchitecture::Unknown:
+ default:
+ return L"Unknown";
+ }
+}
\ No newline at end of file
diff --git a/src/Servers/Kestrel/Core/src/CoreStrings.resx b/src/Servers/Kestrel/Core/src/CoreStrings.resx
index 68908731bf54..346b9c8631fe 100644
--- a/src/Servers/Kestrel/Core/src/CoreStrings.resx
+++ b/src/Servers/Kestrel/Core/src/CoreStrings.resx
@@ -737,4 +737,7 @@ For more information on configuring HTTPS see https://go.microsoft.com/fwlink/?l
The client sent a {frameType} frame to a control stream that was too large.
+
+ Bad chunk extension.
+
\ No newline at end of file
diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs b/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs
index 78416a213472..0762739223ee 100644
--- a/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs
+++ b/src/Servers/Kestrel/Core/src/Internal/Http/Http1ChunkedEncodingMessageBody.cs
@@ -15,6 +15,7 @@ internal sealed class Http1ChunkedEncodingMessageBody : Http1MessageBody
{
// byte consts don't have a data type annotation so we pre-cast it
private const byte ByteCR = (byte)'\r';
+ private const byte ByteLF = (byte)'\n';
// "7FFFFFFF\r\n" is the largest chunk size that could be returned as an int.
private const int MaxChunkPrefixBytes = 10;
@@ -26,6 +27,8 @@ internal sealed class Http1ChunkedEncodingMessageBody : Http1MessageBody
private readonly Pipe _requestBodyPipe;
private ReadResult _readResult;
+ private static readonly bool InsecureChunkedParsing = AppContext.TryGetSwitch("Microsoft.AspNetCore.Server.Kestrel.EnableInsecureChunkedRequestParsing", out var value) && value;
+
public Http1ChunkedEncodingMessageBody(Http1Connection context, bool keepAlive)
: base(context, keepAlive)
{
@@ -343,15 +346,31 @@ private void ParseChunkedPrefix(in ReadOnlySequence buffer, out SequencePo
KestrelBadHttpRequestException.Throw(RequestRejectionReason.BadChunkSizeData);
}
+ // https://www.rfc-editor.org/rfc/rfc9112#section-7.1
+ // chunk = chunk-size [ chunk-ext ] CRLF
+ // chunk-data CRLF
+
+ // https://www.rfc-editor.org/rfc/rfc9112#section-7.1.1
+ // chunk-ext = *( BWS ";" BWS chunk-ext-name
+ // [BWS "=" BWS chunk-ext-val] )
+ // chunk-ext-name = token
+ // chunk-ext-val = token / quoted-string
private void ParseExtension(ReadOnlySequence buffer, out SequencePosition consumed, out SequencePosition examined)
{
- // Chunk-extensions not currently parsed
- // Just drain the data
- examined = buffer.Start;
+ // Chunk-extensions parsed for \r\n and throws for unpaired \r or \n.
do
{
- SequencePosition? extensionCursorPosition = buffer.PositionOf(ByteCR);
+ SequencePosition? extensionCursorPosition;
+ if (InsecureChunkedParsing)
+ {
+ extensionCursorPosition = buffer.PositionOf(ByteCR);
+ }
+ else
+ {
+ extensionCursorPosition = buffer.PositionOfAny(ByteCR, ByteLF);
+ }
+
if (extensionCursorPosition == null)
{
// End marker not found yet
@@ -359,9 +378,10 @@ private void ParseExtension(ReadOnlySequence buffer, out SequencePosition
examined = buffer.End;
AddAndCheckObservedBytes(buffer.Length);
return;
- };
+ }
var extensionCursor = extensionCursorPosition.Value;
+
var charsToByteCRExclusive = buffer.Slice(0, extensionCursor).Length;
var suffixBuffer = buffer.Slice(extensionCursor);
@@ -376,7 +396,9 @@ private void ParseExtension(ReadOnlySequence buffer, out SequencePosition
suffixBuffer = suffixBuffer.Slice(0, 2);
var suffixSpan = suffixBuffer.ToSpan();
- if (suffixSpan[1] == '\n')
+ if (InsecureChunkedParsing
+ ? (suffixSpan[1] == ByteLF)
+ : (suffixSpan[0] == ByteCR && suffixSpan[1] == ByteLF))
{
// We consumed the \r\n at the end of the extension, so switch modes.
_mode = _inputLength > 0 ? Mode.Data : Mode.Trailer;
@@ -385,13 +407,22 @@ private void ParseExtension(ReadOnlySequence buffer, out SequencePosition
examined = suffixBuffer.End;
AddAndCheckObservedBytes(charsToByteCRExclusive + 2);
}
- else
+ else if (InsecureChunkedParsing)
{
+ examined = buffer.Start;
// Don't consume suffixSpan[1] in case it is also a \r.
buffer = buffer.Slice(charsToByteCRExclusive + 1);
consumed = extensionCursor;
AddAndCheckObservedBytes(charsToByteCRExclusive + 1);
}
+ else
+ {
+ consumed = suffixBuffer.End;
+ examined = suffixBuffer.End;
+
+ // We have \rX or \nX, that's an invalid extension.
+ KestrelBadHttpRequestException.Throw(RequestRejectionReason.BadChunkExtension);
+ }
} while (_mode == Mode.Extension);
}
diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/RequestRejectionReason.cs b/src/Servers/Kestrel/Core/src/Internal/Http/RequestRejectionReason.cs
index 0194f09f16d6..3979d2ad7562 100644
--- a/src/Servers/Kestrel/Core/src/Internal/Http/RequestRejectionReason.cs
+++ b/src/Servers/Kestrel/Core/src/Internal/Http/RequestRejectionReason.cs
@@ -16,6 +16,7 @@ internal enum RequestRejectionReason
UnexpectedEndOfRequestContent,
BadChunkSuffix,
BadChunkSizeData,
+ BadChunkExtension,
ChunkedRequestIncomplete,
InvalidRequestTarget,
InvalidCharactersInHeaderName,
@@ -32,5 +33,5 @@ internal enum RequestRejectionReason
MissingHostHeader,
MultipleHostHeaders,
InvalidHostHeader,
- RequestBodyExceedsContentLength
+ RequestBodyExceedsContentLength,
}
diff --git a/src/Servers/Kestrel/Core/src/KestrelBadHttpRequestException.cs b/src/Servers/Kestrel/Core/src/KestrelBadHttpRequestException.cs
index 05ae34f89802..6bfa5bfe60c4 100644
--- a/src/Servers/Kestrel/Core/src/KestrelBadHttpRequestException.cs
+++ b/src/Servers/Kestrel/Core/src/KestrelBadHttpRequestException.cs
@@ -49,6 +49,9 @@ internal static BadHttpRequestException GetException(RequestRejectionReason reas
case RequestRejectionReason.BadChunkSizeData:
ex = new BadHttpRequestException(CoreStrings.BadRequest_BadChunkSizeData, StatusCodes.Status400BadRequest, reason);
break;
+ case RequestRejectionReason.BadChunkExtension:
+ ex = new BadHttpRequestException(CoreStrings.BadRequest_BadChunkExtension, StatusCodes.Status400BadRequest, reason);
+ break;
case RequestRejectionReason.ChunkedRequestIncomplete:
ex = new BadHttpRequestException(CoreStrings.BadRequest_ChunkedRequestIncomplete, StatusCodes.Status400BadRequest, reason);
break;
diff --git a/src/Servers/Kestrel/Core/test/MessageBodyTests.cs b/src/Servers/Kestrel/Core/test/MessageBodyTests.cs
index f0e9dd29ea77..926914975910 100644
--- a/src/Servers/Kestrel/Core/test/MessageBodyTests.cs
+++ b/src/Servers/Kestrel/Core/test/MessageBodyTests.cs
@@ -338,14 +338,14 @@ public async Task ReadExitsGivenIncompleteChunkedExtension()
var stream = new HttpRequestStream(Mock.Of(), reader);
reader.StartAcceptingReads(body);
- input.Add("5;\r\0");
+ input.Add("5;\r");
var buffer = new byte[1024];
var readTask = stream.ReadAsync(buffer, 0, buffer.Length);
Assert.False(readTask.IsCompleted);
- input.Add("\r\r\r\nHello\r\n0\r\n\r\n");
+ input.Add("\nHello\r\n0\r\n\r\n");
Assert.Equal(5, await readTask.DefaultTimeout());
try
diff --git a/src/Servers/Kestrel/test/InMemory.FunctionalTests/ChunkedRequestTests.cs b/src/Servers/Kestrel/test/InMemory.FunctionalTests/ChunkedRequestTests.cs
index 46a364c586de..34428961e022 100644
--- a/src/Servers/Kestrel/test/InMemory.FunctionalTests/ChunkedRequestTests.cs
+++ b/src/Servers/Kestrel/test/InMemory.FunctionalTests/ChunkedRequestTests.cs
@@ -9,6 +9,7 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests.TestTransport;
@@ -21,6 +22,70 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests;
public class ChunkedRequestTests : LoggedTest
{
+ [Theory]
+ [InlineData("2;\rxx\r\nxy\r\n0")] // \r in chunk extensions
+ [InlineData("2;\nxx\r\nxy\r\n0")] // \n in chunk extensions
+ public async Task RejectsInvalidChunkExtensions(string invalidChunkLine)
+ {
+ var testContext = new TestServiceContext(LoggerFactory);
+
+ await using (var server = new TestServer(AppChunked, testContext))
+ {
+ using (var connection = server.CreateConnection())
+ {
+ await connection.Send(
+ "POST / HTTP/1.1",
+ "Host:",
+ "Transfer-Encoding: chunked",
+ "Content-Type: text/plain",
+ "",
+ invalidChunkLine,
+ "",
+ "");
+ await connection.ReceiveEnd(
+ "HTTP/1.1 400 Bad Request",
+ "Content-Length: 0",
+ "Connection: close",
+ $"Date: {testContext.DateHeaderValue}",
+ "",
+ "");
+ }
+ }
+ }
+
+ [Theory]
+ [InlineData("2;a=b;b=c\r\nxy\r\n0")] // Multiple chunk extensions
+ [InlineData("2; \r\nxy\r\n0")] // Space in chunk extensions (BWS)
+ [InlineData("2;;;\r\nxy\r\n0")] // Multiple ';' in chunk extensions
+ [InlineData("2;novalue\r\nxy\r\n0")] // Name only chunk extension
+ //[InlineData("2 ;\r\nxy\r\n0")] // Technically allowed per spec, but we never supported it, and no one should be sending it
+ public async Task AllowsValidChunkExtensions(string chunkLine)
+ {
+ var testContext = new TestServiceContext(LoggerFactory);
+
+ await using (var server = new TestServer(AppChunked, testContext))
+ {
+ using (var connection = server.CreateConnection())
+ {
+ await connection.Send(
+ "POST / HTTP/1.1",
+ "Host:",
+ "Transfer-Encoding: chunked",
+ "Content-Type: text/plain",
+ "",
+ chunkLine,
+ "",
+ "");
+ await connection.Receive(
+ "HTTP/1.1 200 OK",
+ "Content-Length: 2",
+ $"Date: {testContext.DateHeaderValue}",
+ "",
+ "xy");
+ }
+ }
+ }
+
private async Task App(HttpContext httpContext)
{
var request = httpContext.Request;
@@ -1115,4 +1180,86 @@ await connection.Receive(
}
}
}
+
+ [Fact]
+ public async Task MultiReadWithInvalidNewlineAcrossReads()
+ {
+ // Inline so that we know when the first connection.Send has been parsed so we can send the next part
+ var testContext = new TestServiceContext(LoggerFactory)
+ { Scheduler = System.IO.Pipelines.PipeScheduler.Inline };
+
+ var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
+
+ await using (var server = new TestServer(async httpContext =>
+ {
+ var request = httpContext.Request;
+ var readTask = request.BodyReader.ReadAsync();
+ tcs.TrySetResult();
+ var readResult = await readTask;
+ request.BodyReader.AdvanceTo(readResult.Buffer.End);
+ }, testContext))
+ {
+ using (var connection = server.CreateConnection())
+ {
+ await connection.SendAll(
+ "GET / HTTP/1.1",
+ "Host:",
+ "Transfer-Encoding: chunked",
+ "",
+ "1;\r");
+ await tcs.Task;
+ await connection.SendAll(
+ "\r");
+
+ await connection.ReceiveEnd(
+ "HTTP/1.1 400 Bad Request",
+ "Content-Length: 0",
+ "Connection: close",
+ $"Date: {testContext.DateHeaderValue}",
+ "",
+ "");
+ }
+ }
+ }
+
+ [Fact]
+ public async Task InvalidNewlineInFirstReadWithPartialChunkExtension()
+ {
+ // Inline so that we know when the first connection.Send has been parsed so we can send the next part
+ var testContext = new TestServiceContext(LoggerFactory)
+ { Scheduler = System.IO.Pipelines.PipeScheduler.Inline };
+
+ var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
+
+ await using (var server = new TestServer(async httpContext =>
+ {
+ var request = httpContext.Request;
+ var readTask = request.BodyReader.ReadAsync();
+ tcs.TrySetResult();
+ var readResult = await readTask;
+ request.BodyReader.AdvanceTo(readResult.Buffer.End);
+ }, testContext))
+ {
+ using (var connection = server.CreateConnection())
+ {
+ await connection.SendAll(
+ "GET / HTTP/1.1",
+ "Host:",
+ "Transfer-Encoding: chunked",
+ "",
+ "1;\n");
+ await tcs.Task;
+ await connection.SendAll(
+ "t");
+
+ await connection.ReceiveEnd(
+ "HTTP/1.1 400 Bad Request",
+ "Content-Length: 0",
+ "Connection: close",
+ $"Date: {testContext.DateHeaderValue}",
+ "",
+ "");
+ }
+ }
+ }
}
diff --git a/src/SignalR/server/StackExchangeRedis/test/RedisEndToEnd.cs b/src/SignalR/server/StackExchangeRedis/test/RedisEndToEnd.cs
index c3173eb7b178..d60dadfb19fb 100644
--- a/src/SignalR/server/StackExchangeRedis/test/RedisEndToEnd.cs
+++ b/src/SignalR/server/StackExchangeRedis/test/RedisEndToEnd.cs
@@ -184,6 +184,7 @@ public async Task HubConnectionCanSendAndReceiveGroupMessagesGroupNameWithPatter
[ConditionalTheory]
[SkipIfDockerNotPresent]
[MemberData(nameof(TransportTypesAndProtocolTypes))]
+ [QuarantinedTest("https://github.com/dotnet/aspnetcore/issues/63582")]
public async Task CanSendAndReceiveUserMessagesUserNameWithPatternIsTreatedAsLiteral(HttpTransportType transportType, string protocolName)
{
using (StartVerifiableLog())
diff --git a/src/submodules/googletest b/src/submodules/googletest
index 373af2e3df71..eb2d85edd0bf 160000
--- a/src/submodules/googletest
+++ b/src/submodules/googletest
@@ -1 +1 @@
-Subproject commit 373af2e3df71599b87a40ce0e37164523849166b
+Subproject commit eb2d85edd0bff7a712b6aff147cd9f789f0d7d0b