From a4049ce720b5fe85eeab5f2841846fd5bf6ed00d Mon Sep 17 00:00:00 2001
From: Stephen Toub <stoub@microsoft.com>
Date: Wed, 22 Nov 2023 11:49:42 -0500
Subject: [PATCH 1/2] Fix FormatException error message when parsing invalid
 UTF8 inputs

---
 .../src/System/Number.Parsing.cs              | 23 ++++++++++++++++++-
 .../System.Runtime.Tests/System/ByteTests.cs  | 15 +++++++++++-
 .../System/DecimalTests.cs                    | 15 +++++++++++-
 .../System/DoubleTests.cs                     | 15 +++++++++++-
 .../System.Runtime.Tests/System/HalfTests.cs  | 15 +++++++++++-
 .../System/Int128Tests.cs                     | 15 +++++++++++-
 .../System.Runtime.Tests/System/Int16Tests.cs | 15 +++++++++++-
 .../System.Runtime.Tests/System/Int32Tests.cs | 15 +++++++++++-
 .../System.Runtime.Tests/System/Int64Tests.cs | 15 +++++++++++-
 .../System/IntPtrTests.cs                     | 15 +++++++++++-
 .../System.Runtime.Tests/System/SByteTests.cs | 15 +++++++++++-
 .../System/SingleTests.cs                     | 15 +++++++++++-
 .../System/UInt128Tests.cs                    | 15 +++++++++++-
 .../System/UInt16Tests.cs                     | 15 +++++++++++-
 .../System/UInt32Tests.cs                     | 15 +++++++++++-
 .../System/UInt64Tests.cs                     | 15 +++++++++++-
 .../System/UIntPtrTests.cs                    | 15 +++++++++++-
 17 files changed, 246 insertions(+), 17 deletions(-)

diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs
index 77164243594258..0a39cf2c0ae3cf 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs
@@ -8,6 +8,7 @@
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Text;
+using System.Text.Unicode;
 
 namespace System
 {
@@ -1388,7 +1389,27 @@ internal static void ThrowOverflowOrFormatException<TChar, TInteger>(ParsingStat
         internal static void ThrowFormatException<TChar>(ReadOnlySpan<TChar> value)
             where TChar : unmanaged, IUtfChar<TChar>
         {
-            throw new FormatException(SR.Format(SR.Format_InvalidStringWithValue, value.ToString()));
+            string errorMessage;
+
+            if (typeof(TChar) == typeof(byte))
+            {
+                // Decode the UTF8 value into a string we can include in the error message. We're here
+                // because we failed to parse, which also means the bytes might not be valid UTF8,
+                // so fallback to a message that doesn't include the value if the bytes are invalid.
+                // It's possible after we check the bytes for validity that they could be concurrently
+                // mutated, but if that's happening, all bets are off, anyway, and it simply impacts
+                // which exception is thrown.
+                ReadOnlySpan<byte> bytes = MemoryMarshal.Cast<TChar, byte>(value);
+                errorMessage = Utf8.IsValid(bytes) ?
+                    SR.Format(SR.Format_InvalidStringWithValue, Encoding.UTF8.GetString(bytes)) :
+                    SR.Format_InvalidString;
+            }
+            else
+            {
+                errorMessage = SR.Format(SR.Format_InvalidStringWithValue, value.ToString());
+            }
+
+            throw new FormatException(errorMessage);
         }
 
         [DoesNotReturn]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ByteTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ByteTests.cs
index 3593c9b4f470e2..96df8fc909f443 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ByteTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ByteTests.cs
@@ -405,13 +405,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
                     Assert.Equal(0u, result);
                 }
 
-                Assert.Throws(exceptionType, () => byte.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => byte.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(byte.TryParse(valueUtf8, style, provider, out result));
                 Assert.Equal(0u, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => byte.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Theory]
         [MemberData(nameof(ToString_TestData))]
         public static void TryFormat(byte i, string format, IFormatProvider provider, string expected) =>
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DecimalTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DecimalTests.cs
index 3a8c9a344d02cd..5b51bc926b3b32 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DecimalTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DecimalTests.cs
@@ -1037,13 +1037,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
             if (value != null)
             {
                 ReadOnlySpan<byte> valueUtf8 = Encoding.UTF8.GetBytes(value);
-                Assert.Throws(exceptionType, () => decimal.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => decimal.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(decimal.TryParse(valueUtf8, style, provider, out decimal result));
                 Assert.Equal(0, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => decimal.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         public static IEnumerable<object[]> Remainder_Valid_TestData()
         {
             decimal NegativeZero = new decimal(0, 0, 0, true, 0);
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs
index 3c159c0534e7e1..dcfe71c4722822 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs
@@ -658,13 +658,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
             if (value != null)
             {
                 ReadOnlySpan<byte> valueUtf8 = Encoding.UTF8.GetBytes(value);
-                Assert.Throws(exceptionType, () => double.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => double.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(double.TryParse(valueUtf8, style, provider, out double result));
                 Assert.Equal(0, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => double.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Fact]
         public static void PositiveInfinity()
         {
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/HalfTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/HalfTests.cs
index e5b68dfd0bc0d7..f7c769f2c88c34 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/HalfTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/HalfTests.cs
@@ -921,13 +921,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
             if (value != null)
             {
                 ReadOnlySpan<byte> valueUtf8 = Encoding.UTF8.GetBytes(value);
-                Assert.Throws(exceptionType, () => float.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => Half.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(float.TryParse(valueUtf8, style, provider, out float result));
                 Assert.Equal(0, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => Half.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         public static IEnumerable<object[]> ToString_TestData()
         {
             yield return new object[] { -4570.0f, "G", null, "-4570" };
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int128Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int128Tests.cs
index 26fba082e64a83..d3767b224fef65 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int128Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int128Tests.cs
@@ -476,13 +476,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
                     Assert.Equal(0, result);
                 }
 
-                Assert.Throws(exceptionType, () => Int128.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => Int128.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(Int128.TryParse(valueUtf8, style, provider, out result));
                 Assert.Equal(0, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => Int128.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Theory]
         [MemberData(nameof(ToString_TestData))]
         public static void TryFormat(Int128 i, string format, IFormatProvider provider, string expected) =>
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int16Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int16Tests.cs
index 150b035dccb5fc..42e7b39a6a3f61 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int16Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int16Tests.cs
@@ -430,13 +430,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
                     Assert.Equal(0, result);
                 }
 
-                Assert.Throws(exceptionType, () => short.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => short.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(short.TryParse(valueUtf8, style, provider, out result));
                 Assert.Equal(0, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => short.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Theory]
         [MemberData(nameof(ToString_TestData))]
         public static void TryFormat(short i, string format, IFormatProvider provider, string expected) =>
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int32Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int32Tests.cs
index 0b5f7c8250efe3..cbfbfa9830b97f 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int32Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int32Tests.cs
@@ -864,13 +864,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
                     Assert.Equal(0, result);
                 }
 
-                Assert.Throws(exceptionType, () => int.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => int.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(int.TryParse(valueUtf8, style, provider, out result));
                 Assert.Equal(0, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => int.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Theory]
         [InlineData("N")]
         [InlineData("F")]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int64Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int64Tests.cs
index 07b79d94333006..991ac565e04a0e 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int64Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int64Tests.cs
@@ -458,13 +458,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
                     Assert.Equal(0, result);
                 }
 
-                Assert.Throws(exceptionType, () => long.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => long.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(long.TryParse(valueUtf8, style, provider, out result));
                 Assert.Equal(0, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => long.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Theory]
         [MemberData(nameof(ToString_TestData))]
         public static void TryFormat(long i, string format, IFormatProvider provider, string expected) =>
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IntPtrTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IntPtrTests.cs
index f4a16159467f7e..72856049494038 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IntPtrTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IntPtrTests.cs
@@ -1021,13 +1021,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
                     Assert.Equal(default, result);
                 }
 
-                Assert.Throws(exceptionType, () => int.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => nint.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(nint.TryParse(valueUtf8, style, provider, out result));
                 Assert.Equal(default, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => nint.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Theory]
         [InlineData("N")]
         [InlineData("F")]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SByteTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SByteTests.cs
index 0f18bb2e61e02a..15891fd2f1b30c 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SByteTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SByteTests.cs
@@ -424,13 +424,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
                     Assert.Equal(0, result);
                 }
 
-                Assert.Throws(exceptionType, () => sbyte.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => sbyte.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(sbyte.TryParse(valueUtf8, style, provider, out result));
                 Assert.Equal(0, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => sbyte.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Theory]
         [MemberData(nameof(ToString_TestData))]
         public static void TryFormat(sbyte i, string format, IFormatProvider provider, string expected) =>
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs
index 459bdd843f5a9f..8c13a66a84449d 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs
@@ -597,13 +597,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
             if (value != null)
             {
                 ReadOnlySpan<byte> valueUtf8 = Encoding.UTF8.GetBytes(value);
-                Assert.Throws(exceptionType, () => float.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => float.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(float.TryParse(valueUtf8, style, provider, out float result));
                 Assert.Equal(0, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => float.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Fact]
         public static void PositiveInfinity()
         {
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt128Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt128Tests.cs
index f17444e678da0b..19168cf4244d9c 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt128Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt128Tests.cs
@@ -463,13 +463,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
                     Assert.Equal(0u, result);
                 }
 
-                Assert.Throws(exceptionType, () => UInt128.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => UInt128.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(UInt128.TryParse(valueUtf8, style, provider, out result));
                 Assert.Equal(0u, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => UInt128.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Theory]
         [MemberData(nameof(ToString_TestData))]
         public static void TryFormat(UInt128 i, string format, IFormatProvider provider, string expected) =>
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt16Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt16Tests.cs
index 25b4c3b944678e..4e47d10a09354e 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt16Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt16Tests.cs
@@ -402,13 +402,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
                     Assert.Equal(0u, result);
                 }
 
-                Assert.Throws(exceptionType, () => ushort.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => ushort.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(ushort.TryParse(valueUtf8, style, provider, out result));
                 Assert.Equal(0u, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => ushort.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Theory]
         [MemberData(nameof(ToString_TestData))]
         public static void TryFormat(ushort i, string format, IFormatProvider provider, string expected) =>
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt32Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt32Tests.cs
index f912fbd03434a6..7c09e75b9830ed 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt32Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt32Tests.cs
@@ -432,13 +432,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
                     Assert.Equal(0u, result);
                 }
 
-                Assert.Throws(exceptionType, () => uint.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => uint.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(uint.TryParse(valueUtf8, style, provider, out result));
                 Assert.Equal(0u, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => uint.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Theory]
         [MemberData(nameof(ToString_TestData))]
         public static void TryFormat(uint i, string format, IFormatProvider provider, string expected) =>
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt64Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt64Tests.cs
index e47286dca51b27..13ca15f2e7f4f7 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt64Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt64Tests.cs
@@ -445,13 +445,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
                     Assert.Equal(0u, result);
                 }
 
-                Assert.Throws(exceptionType, () => ulong.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => ulong.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(ulong.TryParse(valueUtf8, style, provider, out result));
                 Assert.Equal(0u, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => ulong.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Theory]
         [MemberData(nameof(ToString_TestData))]
         public static void TryFormat(ulong i, string format, IFormatProvider provider, string expected) =>
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UIntPtrTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UIntPtrTests.cs
index 6e1f5d3b460945..9ade4514251fea 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UIntPtrTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UIntPtrTests.cs
@@ -584,13 +584,26 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
                     Assert.Equal(default, result);
                 }
 
-                Assert.Throws(exceptionType, () => nuint.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                Exception e = Assert.Throws(exceptionType, () => nuint.Parse(Encoding.UTF8.GetBytes(value), style, provider));
+                if (e is FormatException fe)
+                {
+                    Assert.Contains(value, fe.Message);
+                }
 
                 Assert.False(nuint.TryParse(valueUtf8, style, provider, out result));
                 Assert.Equal(default, result);
             }
         }
 
+        [Fact]
+        public static void Parse_Utf8Span_InvalidUtf8()
+        {
+            FormatException fe = Assert.Throws<FormatException>(() => nuint.Parse([0xA0]));
+            Assert.DoesNotContain("A0", fe.Message);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
+            Assert.DoesNotContain("\uFFFD", fe.Message);
+        }
+
         [Theory]
         [MemberData(nameof(ToString_TestData))]
         public static void TryFormat(nuint i, string format, IFormatProvider provider, string expected) =>

From 0d92b6c634c5927888aed371829242921c0d93b4 Mon Sep 17 00:00:00 2001
From: Stephen Toub <stoub@microsoft.com>
Date: Mon, 11 Dec 2023 12:02:47 -0500
Subject: [PATCH 2/2] Use Ordinal comparison in Assert.DoesNotContain calls

---
 .../tests/System.Runtime.Tests/System/ByteTests.cs          | 6 +++---
 .../tests/System.Runtime.Tests/System/DecimalTests.cs       | 6 +++---
 .../tests/System.Runtime.Tests/System/DoubleTests.cs        | 6 +++---
 .../tests/System.Runtime.Tests/System/HalfTests.cs          | 6 +++---
 .../tests/System.Runtime.Tests/System/Int128Tests.cs        | 6 +++---
 .../tests/System.Runtime.Tests/System/Int16Tests.cs         | 6 +++---
 .../tests/System.Runtime.Tests/System/Int32Tests.cs         | 6 +++---
 .../tests/System.Runtime.Tests/System/Int64Tests.cs         | 6 +++---
 .../tests/System.Runtime.Tests/System/IntPtrTests.cs        | 6 +++---
 .../tests/System.Runtime.Tests/System/SByteTests.cs         | 6 +++---
 .../tests/System.Runtime.Tests/System/SingleTests.cs        | 6 +++---
 .../tests/System.Runtime.Tests/System/UInt128Tests.cs       | 6 +++---
 .../tests/System.Runtime.Tests/System/UInt16Tests.cs        | 6 +++---
 .../tests/System.Runtime.Tests/System/UInt32Tests.cs        | 6 +++---
 .../tests/System.Runtime.Tests/System/UInt64Tests.cs        | 6 +++---
 .../tests/System.Runtime.Tests/System/UIntPtrTests.cs       | 6 +++---
 16 files changed, 48 insertions(+), 48 deletions(-)

diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ByteTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ByteTests.cs
index 96df8fc909f443..0325507355adae 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ByteTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ByteTests.cs
@@ -420,9 +420,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => byte.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Theory]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DecimalTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DecimalTests.cs
index 5b51bc926b3b32..cf62bd32354494 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DecimalTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DecimalTests.cs
@@ -1052,9 +1052,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => decimal.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         public static IEnumerable<object[]> Remainder_Valid_TestData()
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs
index dcfe71c4722822..bf5e2261995ee0 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs
@@ -673,9 +673,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => double.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Fact]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/HalfTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/HalfTests.cs
index f7c769f2c88c34..1e7f06602c0ec7 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/HalfTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/HalfTests.cs
@@ -936,9 +936,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => Half.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         public static IEnumerable<object[]> ToString_TestData()
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int128Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int128Tests.cs
index d3767b224fef65..8c1910e2fbd8dc 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int128Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int128Tests.cs
@@ -491,9 +491,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => Int128.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Theory]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int16Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int16Tests.cs
index 42e7b39a6a3f61..60414f96e1a8b6 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int16Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int16Tests.cs
@@ -445,9 +445,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => short.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Theory]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int32Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int32Tests.cs
index cbfbfa9830b97f..b0e33fc98783eb 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int32Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int32Tests.cs
@@ -879,9 +879,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => int.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Theory]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int64Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int64Tests.cs
index 991ac565e04a0e..ac902ebdbd7c85 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int64Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int64Tests.cs
@@ -473,9 +473,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => long.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Theory]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IntPtrTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IntPtrTests.cs
index 72856049494038..9b2d96e9797fea 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IntPtrTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/IntPtrTests.cs
@@ -1036,9 +1036,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => nint.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Theory]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SByteTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SByteTests.cs
index 15891fd2f1b30c..7b92f123fd498e 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SByteTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SByteTests.cs
@@ -439,9 +439,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => sbyte.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Theory]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs
index 8c13a66a84449d..25f8d230c80c03 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs
@@ -612,9 +612,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => float.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Fact]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt128Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt128Tests.cs
index 19168cf4244d9c..e3d2c474bcd46b 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt128Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt128Tests.cs
@@ -478,9 +478,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => UInt128.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Theory]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt16Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt16Tests.cs
index 4e47d10a09354e..6ddf7c3bfbaab1 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt16Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt16Tests.cs
@@ -417,9 +417,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => ushort.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Theory]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt32Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt32Tests.cs
index 7c09e75b9830ed..c2f80bba01dda7 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt32Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt32Tests.cs
@@ -447,9 +447,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => uint.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Theory]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt64Tests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt64Tests.cs
index 13ca15f2e7f4f7..de44a6f175884f 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt64Tests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt64Tests.cs
@@ -460,9 +460,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => ulong.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Theory]
diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UIntPtrTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UIntPtrTests.cs
index 9ade4514251fea..6978b9e44eb590 100644
--- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UIntPtrTests.cs
+++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UIntPtrTests.cs
@@ -599,9 +599,9 @@ public static void Parse_Utf8Span_Invalid(string value, NumberStyles style, IFor
         public static void Parse_Utf8Span_InvalidUtf8()
         {
             FormatException fe = Assert.Throws<FormatException>(() => nuint.Parse([0xA0]));
-            Assert.DoesNotContain("A0", fe.Message);
-            Assert.DoesNotContain("ReadOnlySpan", fe.Message);
-            Assert.DoesNotContain("\uFFFD", fe.Message);
+            Assert.DoesNotContain("A0", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("ReadOnlySpan", fe.Message, StringComparison.Ordinal);
+            Assert.DoesNotContain("\uFFFD", fe.Message, StringComparison.Ordinal);
         }
 
         [Theory]
