diff --git a/NuGet.config b/NuGet.config
index 10d96cfd9794d4..73e4341a1899e6 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -9,7 +9,7 @@
-
+
diff --git a/docs/workflow/building/coreclr/cross-building.md b/docs/workflow/building/coreclr/cross-building.md
index d053569cfbcb3d..b77907e7e80583 100644
--- a/docs/workflow/building/coreclr/cross-building.md
+++ b/docs/workflow/building/coreclr/cross-building.md
@@ -155,7 +155,7 @@ docker run --rm \
-v :/runtime \
-w /runtime \
-e ROOTFS_DIR=/crossrootfs/arm64 \
- mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-arm64 \
+ mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net9.0-cross-arm64 \
./build.sh --subset clr --cross --arch arm64
```
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index a8ec9868224f64..76b1fc206a9839 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -13,37 +13,37 @@
https://github.com/dotnet/wcf
7f504aabb1988e9a093c1e74d8040bd52feb2f01
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
https://github.com/dotnet/command-line-api
@@ -65,18 +65,18 @@
4fe10b2349082f474928ac1b97ce207b70dc2307
-
+
https://github.com/dotnet/emsdk
- dee978139950436eec13cadd76e9a438bdb26d4b
+ e2909c00ead6fb5d18a5167ca78f259c639084e0
https://github.com/dotnet/emsdk
- dee978139950436eec13cadd76e9a438bdb26d4b
+ e2909c00ead6fb5d18a5167ca78f259c639084e0
-
+
https://github.com/dotnet/emsdk
- dee978139950436eec13cadd76e9a438bdb26d4b
+ e2909c00ead6fb5d18a5167ca78f259c639084e0
@@ -227,61 +227,61 @@
https://github.com/dotnet/runtime-assets
45c55b97e4006bac84d19a382ace44ef3dcb8d94
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
-
+
https://github.com/dotnet/llvm-project
- ec2b6cf0d0cacbcd527f193599b04725617897a3
+ e5e818c4965ecaba05ab3377a7ce7ab2bb74da52
https://github.com/dotnet/runtime
diff --git a/eng/Versions.props b/eng/Versions.props
index 5ee01ebff50e53..86da21e03fa7df 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -1,11 +1,11 @@
- 9.0.15
+ 9.0.17
9
0
- 15
+ 17
9.0.100
8.0.$([MSBuild]::Add($(PatchVersion),11))
7.0.20
@@ -230,25 +230,25 @@
2.4.18
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
- 9.0.16-servicing.26160.4
+ 9.0.16-servicing.26221.3
9.0.16
$(MicrosoftNETWorkloadEmscriptenCurrentManifest90100Version)
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
- 19.1.0-alpha.1.26152.4
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
+ 19.1.0-alpha.1.26202.3
3.1.7
1.0.406601
diff --git a/eng/pipelines/coreclr/templates/helix-queues-setup.yml b/eng/pipelines/coreclr/templates/helix-queues-setup.yml
index d345553843d941..25fbe960f84e4c 100644
--- a/eng/pipelines/coreclr/templates/helix-queues-setup.yml
+++ b/eng/pipelines/coreclr/templates/helix-queues-setup.yml
@@ -50,7 +50,7 @@ jobs:
# Browser wasm
- ${{ if eq(parameters.platform, 'browser_wasm') }}:
- - (Ubuntu.2204.Amd64)Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-webassembly
+ - (Ubuntu.2604.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64
# iOS devices
- ${{ if in(parameters.platform, 'ios_arm64') }}:
diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml
index 64212601ae5bf8..54ca2643a14e09 100644
--- a/eng/pipelines/libraries/helix-queues-setup.yml
+++ b/eng/pipelines/libraries/helix-queues-setup.yml
@@ -58,8 +58,8 @@ jobs:
# CoreCLR path
- ${{ if and(eq(parameters.jobParameters.isExtraPlatformsBuild, true), ne(parameters.jobParameters.testScope, 'outerloop'))}}:
# extra-platforms CoreCLR (inner loop only)
+ - AzureLinux.3.Amd64.Open
- (Debian.12.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-12-helix-amd64
- - (Mariner.2.0.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-helix-amd64
- ${{ if eq(parameters.jobParameters.testScope, 'outerloop') }}:
# outerloop only CoreCLR
@@ -68,7 +68,7 @@ jobs:
- ${{ if or(ne(parameters.jobParameters.isExtraPlatformsBuild, true), eq(parameters.jobParameters.includeAllPlatforms, true))}}:
# inner and outer loop CoreCLR (general set)
- Ubuntu.2204.Amd64.Open
- - (AzureLinux.3.0.Amd64.Open)AzureLinux.3.Amd64.open@mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-helix-amd64
+ - (AzureLinux.3.0.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-helix-amd64
- (Centos.10.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream-10-helix-amd64
# OSX arm64
@@ -152,15 +152,15 @@ jobs:
# WASI
- ${{ if eq(parameters.platform, 'wasi_wasm') }}:
- - (Ubuntu.2204.Amd64)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-webassembly
+ - (Ubuntu.2604.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64
# Browser WebAssembly
- ${{ if eq(parameters.platform, 'browser_wasm') }}:
- - (Ubuntu.2204.Amd64)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-webassembly
+ - (Ubuntu.2604.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64
# Browser WebAssembly Firefox
- ${{ if eq(parameters.platform, 'browser_wasm_firefox') }}:
- - (Ubuntu.2204.Amd64)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-webassembly
+ - (Ubuntu.2604.Amd64.Open)AzureLinux.3.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-26.04-helix-webassembly-amd64
# Browser WebAssembly windows
- ${{ if in(parameters.platform, 'browser_wasm_win', 'wasi_wasm_win') }}:
diff --git a/src/coreclr/debug/createdump/createdumppal.cpp b/src/coreclr/debug/createdump/createdumppal.cpp
index 03b06a84a46139..990d43b3f3db6e 100644
--- a/src/coreclr/debug/createdump/createdumppal.cpp
+++ b/src/coreclr/debug/createdump/createdumppal.cpp
@@ -24,7 +24,8 @@ typedef BOOL (*PFN_PAL_VirtualUnwindOutOfProc)(
KNONVOLATILE_CONTEXT_POINTERS *contextPointers,
PULONG64 functionStart,
SIZE_T baseAddress,
- UnwindReadMemoryCallback readMemoryCallback);
+ UnwindReadMemoryCallback readMemoryCallback,
+ bool *isSignalFrame);
typedef BOOL (*PFN_PAL_GetUnwindInfoSize)(
SIZE_T baseAddress,
@@ -177,13 +178,14 @@ PAL_VirtualUnwindOutOfProc(
KNONVOLATILE_CONTEXT_POINTERS *contextPointers,
PULONG64 functionStart,
SIZE_T baseAddress,
- UnwindReadMemoryCallback readMemoryCallback)
+ UnwindReadMemoryCallback readMemoryCallback,
+ bool *isSignalFrame)
{
if (!InitializePAL() || g_PAL_VirtualUnwindOutOfProc == nullptr)
{
return FALSE;
}
- return g_PAL_VirtualUnwindOutOfProc(context, contextPointers, functionStart, baseAddress, readMemoryCallback);
+ return g_PAL_VirtualUnwindOutOfProc(context, contextPointers, functionStart, baseAddress, readMemoryCallback, isSignalFrame);
}
BOOL
diff --git a/src/coreclr/debug/createdump/threadinfo.cpp b/src/coreclr/debug/createdump/threadinfo.cpp
index 8eca16d2af1fe4..8db1ad89185f04 100644
--- a/src/coreclr/debug/createdump/threadinfo.cpp
+++ b/src/coreclr/debug/createdump/threadinfo.cpp
@@ -51,6 +51,8 @@ ThreadInfo::UnwindNativeFrames(CONTEXT* pContext)
uint64_t previousSp = 0;
uint64_t previousIp = 0;
int ipMatchCount = 0;
+ bool isSignalFrame = false;
+ bool crossedSignalTrampoline = false;
// For each native frame, add a page around the IP and any unwind info not already
// added in VisitProgramHeader (Linux) and VisitSection (MacOS) to the dump.
@@ -69,10 +71,19 @@ ThreadInfo::UnwindNativeFrames(CONTEXT* pContext)
sp++;
}
#endif
- if (ip == 0 || sp <= previousSp) {
+ // When a signal handler uses SA_ONSTACK (alternate signal stack), the SP can legitimately
+ // decrease when unwinding crosses the signal trampoline back to the original thread stack.
+ // Allow the SP decrease if the current frame is a signal trampoline (detected by the
+ // previous unwind call) and we haven't already crossed one (limit to one crossing to
+ // bound corruption damage).
+ if (ip == 0 || sp == 0 || (sp <= previousSp && (!isSignalFrame || crossedSignalTrampoline))) {
TRACE_VERBOSE("Unwind: sp not increasing or ip == 0 sp %p ip %p\n", (void*)sp, (void*)ip);
break;
}
+ if (sp < previousSp)
+ {
+ crossedSignalTrampoline = true;
+ }
// Break out of the endless loop if the IP matches over a 1000 times. This is a fallback
// behavior of libunwind when the module the IP is in doesn't have unwind info and for
// simple stack overflows. The stack memory is added to the dump in GetThreadStack and
@@ -104,7 +115,8 @@ ThreadInfo::UnwindNativeFrames(CONTEXT* pContext)
// Unwind the native frame adding all the memory accessed to the core dump via the read memory adapter.
ULONG64 functionStart;
- if (!PAL_VirtualUnwindOutOfProc(pContext, nullptr, &functionStart, baseAddress, ReadMemoryAdapter)) {
+ isSignalFrame = false;
+ if (!PAL_VirtualUnwindOutOfProc(pContext, nullptr, &functionStart, baseAddress, ReadMemoryAdapter, &isSignalFrame)) {
TRACE("Unwind: PAL_VirtualUnwindOutOfProc returned false\n");
break;
}
diff --git a/src/coreclr/debug/daccess/dacfn.cpp b/src/coreclr/debug/daccess/dacfn.cpp
index 07cb785ee4ae10..5f383f4ec47d7b 100644
--- a/src/coreclr/debug/daccess/dacfn.cpp
+++ b/src/coreclr/debug/daccess/dacfn.cpp
@@ -248,7 +248,7 @@ typedef BOOL(*UnwindReadMemoryCallback)(PVOID address, PVOID buffer, SIZE_T size
extern
BOOL
-PAL_VirtualUnwindOutOfProc(PT_CONTEXT context, PT_KNONVOLATILE_CONTEXT_POINTERS contextPointers, PULONG64 functionStart, SIZE_T baseAddress, UnwindReadMemoryCallback readMemoryCallback);
+PAL_VirtualUnwindOutOfProc(PT_CONTEXT context, PT_KNONVOLATILE_CONTEXT_POINTERS contextPointers, PULONG64 functionStart, SIZE_T baseAddress, UnwindReadMemoryCallback readMemoryCallback, bool *isSignalFrame);
#endif
HRESULT
@@ -282,7 +282,7 @@ DacVirtualUnwind(ULONG32 threadId, PT_CONTEXT context, PT_KNONVOLATILE_CONTEXT_P
hr = S_OK;
SIZE_T baseAddress = DacGlobalBase();
- if (baseAddress == 0 || !PAL_VirtualUnwindOutOfProc(context, contextPointers, nullptr, baseAddress, DacReadAllAdapter))
+ if (baseAddress == 0 || !PAL_VirtualUnwindOutOfProc(context, contextPointers, nullptr, baseAddress, DacReadAllAdapter, nullptr))
{
hr = E_FAIL;
}
diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h
index e4a520c1dcf5c9..441f45f96cff34 100644
--- a/src/coreclr/pal/inc/pal.h
+++ b/src/coreclr/pal/inc/pal.h
@@ -2612,7 +2612,7 @@ typedef BOOL(*UnwindReadMemoryCallback)(PVOID address, PVOID buffer, SIZE_T size
PALIMPORT BOOL PALAPI PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers);
-PALIMPORT BOOL PALAPI PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers, PULONG64 functionStart, SIZE_T baseAddress, UnwindReadMemoryCallback readMemoryCallback);
+PALIMPORT BOOL PALAPI PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers, PULONG64 functionStart, SIZE_T baseAddress, UnwindReadMemoryCallback readMemoryCallback, bool *isSignalFrame);
PALIMPORT BOOL PALAPI PAL_GetUnwindInfoSize(SIZE_T baseAddress, ULONG64 ehFrameHdrAddr, UnwindReadMemoryCallback readMemoryCallback, PULONG64 ehFrameStart, PULONG64 ehFrameSize);
diff --git a/src/coreclr/pal/src/exception/remote-unwind.cpp b/src/coreclr/pal/src/exception/remote-unwind.cpp
index 05cba618a10222..5ef61afe4ad28d 100644
--- a/src/coreclr/pal/src/exception/remote-unwind.cpp
+++ b/src/coreclr/pal/src/exception/remote-unwind.cpp
@@ -2451,10 +2451,11 @@ static unw_accessors_t unwind_accessors = init_unwind_accessors();
functionStart - the pointer to return the starting address of the function or nullptr
baseAddress - base address of the module to find the unwind info
readMemoryCallback - reads memory from the target
+ isSignalFrame - output parameter: set to true if the unwound-to frame is a signal trampoline
--*/
BOOL
PALAPI
-PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers, PULONG64 functionStart, SIZE_T baseAddress, UnwindReadMemoryCallback readMemoryCallback)
+PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers, PULONG64 functionStart, SIZE_T baseAddress, UnwindReadMemoryCallback readMemoryCallback, bool *isSignalFrame)
{
unw_addr_space_t addrSpace = 0;
unw_cursor_t cursor;
@@ -2462,6 +2463,11 @@ PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *cont
BOOL result = FALSE;
int st;
+ if (isSignalFrame)
+ {
+ *isSignalFrame = false;
+ }
+
info.BaseAddress = baseAddress;
info.Context = context;
info.FunctionStart = 0;
@@ -2533,6 +2539,14 @@ PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *cont
goto exit;
}
+ // Check if the frame we landed on is a signal trampoline. When a signal handler uses
+ // SA_ONSTACK, stepping from a signal frame crosses from the alternate signal stack to the
+ // original thread stack, which can cause the SP to decrease.
+ if (isSignalFrame && unw_is_signal_frame(&cursor) > 0)
+ {
+ *isSignalFrame = true;
+ }
+
UnwindContextToContext(&cursor, context);
if (contextPointers != NULL)
@@ -2699,7 +2713,7 @@ PAL_GetUnwindInfoSize(SIZE_T baseAddress, ULONG64 ehFrameHdrAddr, UnwindReadMemo
BOOL
PALAPI
-PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers, PULONG64 functionStart, SIZE_T baseAddress, UnwindReadMemoryCallback readMemoryCallback)
+PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextPointers, PULONG64 functionStart, SIZE_T baseAddress, UnwindReadMemoryCallback readMemoryCallback, bool *isSignalFrame)
{
return FALSE;
}
diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressParser.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressParser.cs
index c3479598be7466..0770f80b72dbc7 100644
--- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressParser.cs
+++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressParser.cs
@@ -69,6 +69,20 @@ private static bool TryParseAddress(string data, bool expectMultipleAddresses, r
Debug.Assert(!string.IsNullOrEmpty(data));
Debug.Assert(index >= 0 && index < data.Length, $"Index out of range: {index}, {data.Length}");
+ // Check for CR or LF characters which are not allowed in mail addresses.
+ // Only scan on the first call (index == data.Length - 1) to avoid repeated O(n) scans
+ // when parsing multiple addresses from the same string.
+ if (index == data.Length - 1 && MailBnfHelper.HasCROrLF(data))
+ {
+ if (throwExceptionIfFail)
+ {
+ throw new FormatException(SR.MailAddressInvalidFormat);
+ }
+
+ parseAddressInfo = default;
+ return false;
+ }
+
// Parsed components to be assembled as a MailAddress later
string? displayName;
diff --git a/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs b/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs
index c8c5734b04cf44..22ab02470d810d 100644
--- a/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs
+++ b/src/libraries/System.Net.Mail/tests/Functional/SmtpClientTest.cs
@@ -580,37 +580,17 @@ public void TestGssapiAuthentication()
[Theory]
[MemberData(nameof(SendMail_MultiLineDomainLiterals_Data))]
- public async Task SendMail_MultiLineDomainLiterals_Disabled_Throws(string from, string to, bool asyncSend)
+ public void SendMail_MultiLineDomainLiterals_Disabled_Throws(string from, string to)
{
- using var server = new LoopbackSmtpServer();
-
- using SmtpClient client = server.CreateClient();
- client.Credentials = new NetworkCredential("Foo", "Bar");
-
- using var msg = new MailMessage(@from, @to, "subject", "body");
-
- await Assert.ThrowsAsync(async () =>
- {
- if (asyncSend)
- {
- await client.SendMailAsync(msg).WaitAsync(TimeSpan.FromSeconds(30));
- }
- else
- {
- client.Send(msg);
- }
- });
+ Assert.Throws(() => new MailMessage(@from, @to, "subject", "body"));
}
public static IEnumerable