diff options
author | Brennan <brecon@microsoft.com> | 2022-04-30 00:05:28 +0300 |
---|---|---|
committer | Brennan <brecon@microsoft.com> | 2022-04-30 00:05:28 +0300 |
commit | eddd87114dbda811912d57928a755ece78859f7c (patch) | |
tree | a5290a1b8f4ffa5aa8995f9140c3151fee1bd984 | |
parent | 26b6365cfe7f83b744e224cb94ef7c95b751e0a1 (diff) |
Update SDK and use 'u8' string literalsbrecon/u8sdk
18 files changed, 64 insertions, 62 deletions
diff --git a/global.json b/global.json index 768651dc9a..f449c425a6 100644 --- a/global.json +++ b/global.json @@ -1,9 +1,9 @@ { "sdk": { - "version": "7.0.100-preview.4.22218.29" + "version": "7.0.100-preview.5.22228.6" }, "tools": { - "dotnet": "7.0.100-preview.4.22218.29", + "dotnet": "7.0.100-preview.5.22228.6", "runtimes": { "dotnet/x86": [ "$(MicrosoftNETCoreBrowserDebugHostTransportVersion)" diff --git a/src/DataProtection/Abstractions/test/DataProtectionCommonExtensionsTests.cs b/src/DataProtection/Abstractions/test/DataProtectionCommonExtensionsTests.cs index 35698a369e..21f0d85f56 100644 --- a/src/DataProtection/Abstractions/test/DataProtectionCommonExtensionsTests.cs +++ b/src/DataProtection/Abstractions/test/DataProtectionCommonExtensionsTests.cs @@ -249,7 +249,8 @@ public class DataProtectionCommonExtensionsTests // Act & assert var ex = Assert.Throws<CryptographicException>(() => { - mockProtector.Object.Protect("Hello\ud800"); + string plainText = "Hello\ud800"; + mockProtector.Object.Protect(plainText); }); Assert.IsAssignableFrom<EncoderFallbackException>(ex.InnerException); } @@ -262,7 +263,8 @@ public class DataProtectionCommonExtensionsTests mockProtector.Setup(p => p.Protect(new byte[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f })).Returns(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 }); // Act - string retVal = mockProtector.Object.Protect("Hello"); + string plainText = "Hello"; + string retVal = mockProtector.Object.Protect(plainText); // Assert Assert.Equal("AQIDBAU", retVal); @@ -277,7 +279,8 @@ public class DataProtectionCommonExtensionsTests // Act & assert var ex = Assert.Throws<CryptographicException>(() => { - mockProtector.Object.Unprotect("A"); + string data = "A"; + mockProtector.Object.Unprotect(data); }); } @@ -291,7 +294,8 @@ public class DataProtectionCommonExtensionsTests // Act & assert var ex = Assert.Throws<CryptographicException>(() => { - mockProtector.Object.Unprotect("AQIDBAU"); + string data = "AQIDBAU"; + mockProtector.Object.Unprotect(data); }); Assert.IsAssignableFrom<DecoderFallbackException>(ex.InnerException); } @@ -304,7 +308,8 @@ public class DataProtectionCommonExtensionsTests mockProtector.Setup(p => p.Unprotect(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 })).Returns(new byte[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f }); // Act - string retVal = DataProtectionCommonExtensions.Unprotect(mockProtector.Object, "AQIDBAU"); + string data = "AQIDBAU"; + string retVal = mockProtector.Object.Unprotect(data); // Assert Assert.Equal("Hello", retVal); diff --git a/src/DataProtection/Extensions/test/DataProtectionAdvancedExtensionsTests.cs b/src/DataProtection/Extensions/test/DataProtectionAdvancedExtensionsTests.cs index b5de038ff6..ec5f858c74 100644 --- a/src/DataProtection/Extensions/test/DataProtectionAdvancedExtensionsTests.cs +++ b/src/DataProtection/Extensions/test/DataProtectionAdvancedExtensionsTests.cs @@ -23,7 +23,7 @@ public class DataProtectionAdvancedExtensionsTests mockDataProtector.Setup(o => o.Protect(plaintextAsBytes, expiration)).Returns(new byte[] { 0x01, 0x02 }); // Act - string protectedPayload = mockDataProtector.Object.Protect("this is plaintext", expiration); + string protectedPayload = DataProtectionAdvancedExtensions.Protect(mockDataProtector.Object, "this is plaintext", expiration); // Assert Assert.Equal(SampleEncodedString, protectedPayload); @@ -86,7 +86,7 @@ public class DataProtectionAdvancedExtensionsTests mockDataProtector.Setup(o => o.Unprotect(new byte[] { 0x01, 0x02 }, out controlExpiration)).Returns(Encoding.UTF8.GetBytes("this is plaintext")); // Act - string unprotectedPayload = mockDataProtector.Object.Unprotect(SampleEncodedString, out var testExpiration); + string unprotectedPayload = DataProtectionAdvancedExtensions.Unprotect(mockDataProtector.Object, SampleEncodedString, out var testExpiration); // Assert Assert.Equal("this is plaintext", unprotectedPayload); diff --git a/src/DataProtection/Extensions/test/DataProtectionProviderTests.cs b/src/DataProtection/Extensions/test/DataProtectionProviderTests.cs index ab0e6877ce..a1884143a8 100644 --- a/src/DataProtection/Extensions/test/DataProtectionProviderTests.cs +++ b/src/DataProtection/Extensions/test/DataProtectionProviderTests.cs @@ -32,7 +32,8 @@ public class DataProtectionProviderTests // Step 2: instantiate the system and round-trip a payload var protector = DataProtectionProvider.Create(directory).CreateProtector("purpose"); - Assert.Equal("payload", protector.Unprotect(protector.Protect("payload"))); + string plainText = "payload"; + Assert.Equal(plainText, protector.Unprotect(protector.Protect(plainText))); // Step 3: validate that there's now a single key in the directory and that it's not protected var allFiles = directory.GetFiles(); @@ -67,7 +68,8 @@ public class DataProtectionProviderTests }); var protector = provider.CreateProtector("Protector"); - Assert.Equal("payload", protector.Unprotect(protector.Protect("payload"))); + string plainText = "payload"; + Assert.Equal(plainText, protector.Unprotect(protector.Protect(plainText))); // Step 2: Validate that there's now a single key in the directory var newFileName = Assert.Single(Directory.GetFiles(keysPath)); @@ -101,7 +103,8 @@ public class DataProtectionProviderTests { configure.ProtectKeysWithDpapi(); }).CreateProtector("purpose"); - Assert.Equal("payload", protector.Unprotect(protector.Protect("payload"))); + string plainText = "payload"; + Assert.Equal(plainText, protector.Unprotect(protector.Protect(plainText))); // Step 3: validate that there's now a single key in the directory and that it's protected with DPAPI var allFiles = directory.GetFiles(); @@ -142,12 +145,13 @@ public class DataProtectionProviderTests // Step 2: instantiate the system and round-trip a payload var protector = DataProtectionProvider.Create(directory, certificate).CreateProtector("purpose"); - var data = protector.Protect("payload"); + string plainText = "payload"; + var data = protector.Protect(plainText); // add a cert without the private key to ensure the decryption will still fallback to the cert store var certWithoutKey = new X509Certificate2(Path.Combine(GetTestFilesPath(), "TestCertWithoutPrivateKey.pfx"), "password"); var unprotector = DataProtectionProvider.Create(directory, o => o.UnprotectKeysWithAnyCertificate(certWithoutKey)).CreateProtector("purpose"); - Assert.Equal("payload", unprotector.Unprotect(data)); + Assert.Equal(plainText, unprotector.Unprotect(data)); // Step 3: validate that there's now a single key in the directory and that it's is protected using the certificate var allFiles = directory.GetFiles(); @@ -193,13 +197,14 @@ public class DataProtectionProviderTests var certWithKey = new X509Certificate2(Path.Combine(GetTestFilesPath(), "TestCert3.pfx"), "password3"); var protector = DataProtectionProvider.Create(directory, certWithKey).CreateProtector("purpose"); - var data = protector.Protect("payload"); + string plainText = "payload"; + var data = protector.Protect(plainText); var keylessUnprotector = DataProtectionProvider.Create(directory).CreateProtector("purpose"); Assert.Throws<CryptographicException>(() => keylessUnprotector.Unprotect(data)); var unprotector = DataProtectionProvider.Create(directory, o => o.UnprotectKeysWithAnyCertificate(certInStore, certWithKey)).CreateProtector("purpose"); - Assert.Equal("payload", unprotector.Unprotect(data)); + Assert.Equal(plainText, unprotector.Unprotect(data)); } finally { @@ -226,7 +231,9 @@ public class DataProtectionProviderTests // Step 2: instantiate the system and round-trip a payload var protector = DataProtectionProvider.Create(directory, certificate).CreateProtector("purpose"); - Assert.Equal("payload", protector.Unprotect(protector.Protect("payload"))); + var plainText = "payload"; + Assert.Equal(plainText, + protector.Unprotect(protector.Protect(plainText))); // Step 3: validate that there's now a single key in the directory and that it's is protected using the certificate var allFiles = directory.GetFiles(); @@ -273,7 +280,8 @@ public class DataProtectionProviderTests .Create(directory, certificate) .CreateProtector("purpose"); - var data = protector.Protect("payload"); + string plainText = "payload"; + var data = protector.Protect(plainText); // Step 3: validate that there's now a single key in the directory and that it's is protected using the certificate var allFiles = directory.GetFiles(); @@ -286,7 +294,7 @@ public class DataProtectionProviderTests // Step 4: setup a second system and validate it can decrypt keys and unprotect data var unprotector = DataProtectionProvider.Create(directory, b => b.UnprotectKeysWithAnyCertificate(certificate)); - Assert.Equal("payload", unprotector.CreateProtector("purpose").Unprotect(data)); + Assert.Equal(plainText, unprotector.CreateProtector("purpose").Unprotect(data)); }); } diff --git a/src/Http/Headers/src/ContentDispositionHeaderValue.cs b/src/Http/Headers/src/ContentDispositionHeaderValue.cs index e0f0f99064..0a7882c8d1 100644 --- a/src/Http/Headers/src/ContentDispositionHeaderValue.cs +++ b/src/Http/Headers/src/ContentDispositionHeaderValue.cs @@ -32,8 +32,8 @@ public class ContentDispositionHeaderValue private static readonly char[] QuestionMark = new char[] { '?' }; private static readonly char[] SingleQuote = new char[] { '\'' }; private static readonly char[] EscapeChars = new char[] { '\\', '"' }; - private static ReadOnlySpan<byte> MimePrefix => new byte[] { (byte)'"', (byte)'=', (byte)'?', (byte)'u', (byte)'t', (byte)'f', (byte)'-', (byte)'8', (byte)'?', (byte)'B', (byte)'?' }; - private static ReadOnlySpan<byte> MimeSuffix => new byte[] { (byte)'?', (byte)'=', (byte)'"' }; + private static ReadOnlySpan<byte> MimePrefix => "\"=?utf-8?B?"u8; + private static ReadOnlySpan<byte> MimeSuffix => "?=\""u8; private static readonly HttpHeaderParser<ContentDispositionHeaderValue> Parser = new GenericHeaderParser<ContentDispositionHeaderValue>(false, GetDispositionTypeLength); diff --git a/src/Http/WebUtilities/src/FormPipeReader.cs b/src/Http/WebUtilities/src/FormPipeReader.cs index 845ad7bf6b..d803dc7f72 100644 --- a/src/Http/WebUtilities/src/FormPipeReader.cs +++ b/src/Http/WebUtilities/src/FormPipeReader.cs @@ -26,8 +26,8 @@ public class FormPipeReader // Used for UTF8/ASCII (precalculated for fast path) // This uses C# compiler's ability to refer to static data directly. For more information see https://vcsjones.dev/2019/02/01/csharp-readonly-span-bytes-static - private static ReadOnlySpan<byte> UTF8EqualEncoded => new byte[] { (byte)'=' }; - private static ReadOnlySpan<byte> UTF8AndEncoded => new byte[] { (byte)'&' }; + private static ReadOnlySpan<byte> UTF8EqualEncoded => "="u8; + private static ReadOnlySpan<byte> UTF8AndEncoded => "&"u8; // Used for other encodings private readonly byte[]? _otherEqualEncoding; @@ -251,7 +251,7 @@ public class FormPipeReader if (!isFinalBlock) { // +2 to account for '&' and '=' - if ((sequenceReader.Length - consumedBytes) > (long)KeyLengthLimit + (long)ValueLengthLimit + 2) + if ((sequenceReader.Length - consumedBytes) > (long)KeyLengthLimit + (long)ValueLengthLimit + 2) { ThrowKeyOrValueTooLargeException(); } diff --git a/src/Middleware/WebSockets/src/HandshakeHelpers.cs b/src/Middleware/WebSockets/src/HandshakeHelpers.cs index 446236b8d5..f21fdec07f 100644 --- a/src/Middleware/WebSockets/src/HandshakeHelpers.cs +++ b/src/Middleware/WebSockets/src/HandshakeHelpers.cs @@ -14,15 +14,8 @@ namespace Microsoft.AspNetCore.WebSockets; internal static class HandshakeHelpers { - // "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" // This uses C# compiler's ability to refer to static data directly. For more information see https://vcsjones.dev/2019/02/01/csharp-readonly-span-bytes-static - private static ReadOnlySpan<byte> EncodedWebSocketKey => new byte[] - { - (byte)'2', (byte)'5', (byte)'8', (byte)'E', (byte)'A', (byte)'F', (byte)'A', (byte)'5', (byte)'-', - (byte)'E', (byte)'9', (byte)'1', (byte)'4', (byte)'-', (byte)'4', (byte)'7', (byte)'D', (byte)'A', - (byte)'-', (byte)'9', (byte)'5', (byte)'C', (byte)'A', (byte)'-', (byte)'C', (byte)'5', (byte)'A', - (byte)'B', (byte)'0', (byte)'D', (byte)'C', (byte)'8', (byte)'5', (byte)'B', (byte)'1', (byte)'1' - }; + private static ReadOnlySpan<byte> EncodedWebSocketKey => "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"u8; // Verify Method, Upgrade, Connection, version, key, etc.. public static void GenerateResponseHeaders(string key, string? subProtocol, IHeaderDictionary headers) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/ChunkWriter.cs b/src/Servers/Kestrel/Core/src/Internal/Http/ChunkWriter.cs index 2a2dcd0dd2..deaa411eac 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/ChunkWriter.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/ChunkWriter.cs @@ -25,7 +25,7 @@ internal static class ChunkWriter // This must be explicity typed as ReadOnlySpan<byte> // It then becomes a non-allocating mapping to the data section of the assembly. // For more information see https://vcsjones.dev/2019/02/01/csharp-readonly-span-bytes-static - ReadOnlySpan<byte> hex = new byte[16] { (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f' }; + ReadOnlySpan<byte> hex = "0123456789abcdef"u8; var offset = 0; for (shift = total; shift >= 0; shift -= 4) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/DateHeaderValueManager.cs b/src/Servers/Kestrel/Core/src/Internal/Http/DateHeaderValueManager.cs index 3576db3b44..2ee8b52730 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/DateHeaderValueManager.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/DateHeaderValueManager.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; internal class DateHeaderValueManager : IHeartbeatHandler { // This uses C# compiler's ability to refer to static data directly. For more information see https://vcsjones.dev/2019/02/01/csharp-readonly-span-bytes-static - private static ReadOnlySpan<byte> DatePreambleBytes => new byte[8] { (byte)'\r', (byte)'\n', (byte)'D', (byte)'a', (byte)'t', (byte)'e', (byte)':', (byte)' ' }; + private static ReadOnlySpan<byte> DatePreambleBytes => "\r\nDate: "u8; private DateHeaderValues? _dateValues; diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs b/src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs index 7254e1b338..d29fbee972 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/Http1OutputProducer.cs @@ -15,14 +15,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; internal class Http1OutputProducer : IHttpOutputProducer, IDisposable { // Use C#7.3's ReadOnlySpan<byte> optimization for static data https://vcsjones.com/2019/02/01/csharp-readonly-span-bytes-static/ - // "HTTP/1.1 100 Continue\r\n\r\n" - private static ReadOnlySpan<byte> ContinueBytes => new byte[] { (byte)'H', (byte)'T', (byte)'T', (byte)'P', (byte)'/', (byte)'1', (byte)'.', (byte)'1', (byte)' ', (byte)'1', (byte)'0', (byte)'0', (byte)' ', (byte)'C', (byte)'o', (byte)'n', (byte)'t', (byte)'i', (byte)'n', (byte)'u', (byte)'e', (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; - // "HTTP/1.1 " - private static ReadOnlySpan<byte> HttpVersion11Bytes => new byte[] { (byte)'H', (byte)'T', (byte)'T', (byte)'P', (byte)'/', (byte)'1', (byte)'.', (byte)'1', (byte)' ' }; - // "\r\n\r\n" - private static ReadOnlySpan<byte> EndHeadersBytes => new byte[] { (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; - // "0\r\n\r\n" - private static ReadOnlySpan<byte> EndChunkedResponseBytes => new byte[] { (byte)'0', (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; + private static ReadOnlySpan<byte> ContinueBytes => "HTTP/1.1 100 Continue\r\n\r\n"u8; + private static ReadOnlySpan<byte> HttpVersion11Bytes => "HTTP/1.1 "u8; + private static ReadOnlySpan<byte> EndHeadersBytes => "\r\n\r\n"u8; + private static ReadOnlySpan<byte> EndChunkedResponseBytes => "0\r\n\r\n"u8; private const int MaxBeginChunkLength = 10; private const int EndChunkLength = 2; diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpResponseHeaders.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpResponseHeaders.cs index cd449dc37e..768649ac40 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpResponseHeaders.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpResponseHeaders.cs @@ -16,8 +16,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; internal sealed partial class HttpResponseHeaders : HttpHeaders { // This uses C# compiler's ability to refer to static data directly. For more information see https://vcsjones.dev/2019/02/01/csharp-readonly-span-bytes-static - private static ReadOnlySpan<byte> CrLf => new[] { (byte)'\r', (byte)'\n' }; - private static ReadOnlySpan<byte> ColonSpace => new[] { (byte)':', (byte)' ' }; + private static ReadOnlySpan<byte> CrLf => "\r\n"u8; + private static ReadOnlySpan<byte> ColonSpace => ": "u8; public Func<string, Encoding?> EncodingSelector { get; set; } diff --git a/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs b/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs index 462e56533e..288eac400e 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs @@ -26,15 +26,15 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http3; internal abstract partial class Http3Stream : HttpProtocol, IHttp3Stream, IHttpStreamHeadersHandler, IThreadPoolWorkItem { - private static ReadOnlySpan<byte> AuthorityBytes => new byte[10] { (byte)':', (byte)'a', (byte)'u', (byte)'t', (byte)'h', (byte)'o', (byte)'r', (byte)'i', (byte)'t', (byte)'y' }; - private static ReadOnlySpan<byte> MethodBytes => new byte[7] { (byte)':', (byte)'m', (byte)'e', (byte)'t', (byte)'h', (byte)'o', (byte)'d' }; - private static ReadOnlySpan<byte> PathBytes => new byte[5] { (byte)':', (byte)'p', (byte)'a', (byte)'t', (byte)'h' }; - private static ReadOnlySpan<byte> SchemeBytes => new byte[7] { (byte)':', (byte)'s', (byte)'c', (byte)'h', (byte)'e', (byte)'m', (byte)'e' }; - private static ReadOnlySpan<byte> StatusBytes => new byte[7] { (byte)':', (byte)'s', (byte)'t', (byte)'a', (byte)'t', (byte)'u', (byte)'s' }; - private static ReadOnlySpan<byte> ConnectionBytes => new byte[10] { (byte)'c', (byte)'o', (byte)'n', (byte)'n', (byte)'e', (byte)'c', (byte)'t', (byte)'i', (byte)'o', (byte)'n' }; - private static ReadOnlySpan<byte> TeBytes => new byte[2] { (byte)'t', (byte)'e' }; - private static ReadOnlySpan<byte> TrailersBytes => new byte[8] { (byte)'t', (byte)'r', (byte)'a', (byte)'i', (byte)'l', (byte)'e', (byte)'r', (byte)'s' }; - private static ReadOnlySpan<byte> ConnectBytes => new byte[7] { (byte)'C', (byte)'O', (byte)'N', (byte)'N', (byte)'E', (byte)'C', (byte)'T' }; + private static ReadOnlySpan<byte> AuthorityBytes => ":authority"u8; + private static ReadOnlySpan<byte> MethodBytes => ":method"u8; + private static ReadOnlySpan<byte> PathBytes => ":path"u8; + private static ReadOnlySpan<byte> SchemeBytes => ":scheme"u8; + private static ReadOnlySpan<byte> StatusBytes => ":status"u8; + private static ReadOnlySpan<byte> ConnectionBytes => "connection"u8; + private static ReadOnlySpan<byte> TeBytes => "te"u8; + private static ReadOnlySpan<byte> TrailersBytes => "trailers"u8; + private static ReadOnlySpan<byte> ConnectBytes => "CONNECT"u8; private const PseudoHeaderFields _mandatoryRequestPseudoHeaderFields = PseudoHeaderFields.Method | PseudoHeaderFields.Path | PseudoHeaderFields.Scheme; diff --git a/src/Servers/Kestrel/Core/src/Internal/HttpConnection.cs b/src/Servers/Kestrel/Core/src/Internal/HttpConnection.cs index c057a14124..360c81587a 100644 --- a/src/Servers/Kestrel/Core/src/Internal/HttpConnection.cs +++ b/src/Servers/Kestrel/Core/src/Internal/HttpConnection.cs @@ -18,7 +18,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal; internal class HttpConnection : ITimeoutHandler { // Use C#7.3's ReadOnlySpan<byte> optimization for static data https://vcsjones.com/2019/02/01/csharp-readonly-span-bytes-static/ - private static ReadOnlySpan<byte> Http2Id => new[] { (byte)'h', (byte)'2' }; + private static ReadOnlySpan<byte> Http2Id => "h2"u8; private readonly BaseHttpConnectionContext _context; private readonly ISystemClock _systemClock; diff --git a/src/Shared/CertificateGeneration/CertificateManager.cs b/src/Shared/CertificateGeneration/CertificateManager.cs index 9f7baf1de2..6a49119d4b 100644 --- a/src/Shared/CertificateGeneration/CertificateManager.cs +++ b/src/Shared/CertificateGeneration/CertificateManager.cs @@ -485,7 +485,7 @@ internal abstract class CertificateManager char[] pem; if (password != null) { - keyBytes = key.ExportEncryptedPkcs8PrivateKey(password, new PbeParameters(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 100000)); + keyBytes = key.ExportEncryptedPkcs8PrivateKey((ReadOnlySpan<char>)password, new PbeParameters(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 100000)); pem = PemEncoding.Write("ENCRYPTED PRIVATE KEY", keyBytes); pemEnvelope = Encoding.ASCII.GetBytes(pem); } @@ -494,11 +494,11 @@ internal abstract class CertificateManager // Export the key first to an encrypted PEM to avoid issues with System.Security.Cryptography.Cng indicating that the operation is not supported. // This is likely by design to avoid exporting the key by mistake. // To bypass it, we export the certificate to pem temporarily and then we import it and export it as unprotected PEM. - keyBytes = key.ExportEncryptedPkcs8PrivateKey("", new PbeParameters(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 1)); + keyBytes = key.ExportEncryptedPkcs8PrivateKey((ReadOnlySpan<char>)"", new PbeParameters(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 1)); pem = PemEncoding.Write("ENCRYPTED PRIVATE KEY", keyBytes); key.Dispose(); key = RSA.Create(); - key.ImportFromEncryptedPem(pem, ""); + key.ImportFromEncryptedPem(pem, (ReadOnlySpan<char>)""); Array.Clear(keyBytes, 0, keyBytes.Length); Array.Clear(pem, 0, pem.Length); keyBytes = key.ExportPkcs8PrivateKey(); diff --git a/src/Shared/Http2cat/Http2Utilities.cs b/src/Shared/Http2cat/Http2Utilities.cs index c5479147e1..b9ac25c4fd 100644 --- a/src/Shared/Http2cat/Http2Utilities.cs +++ b/src/Shared/Http2cat/Http2Utilities.cs @@ -26,7 +26,7 @@ namespace Microsoft.AspNetCore.Http2Cat; internal class Http2Utilities : IHttpStreamHeadersHandler { - public static ReadOnlySpan<byte> ClientPreface => new byte[24] { (byte)'P', (byte)'R', (byte)'I', (byte)' ', (byte)'*', (byte)' ', (byte)'H', (byte)'T', (byte)'T', (byte)'P', (byte)'/', (byte)'2', (byte)'.', (byte)'0', (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n', (byte)'S', (byte)'M', (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; + public static ReadOnlySpan<byte> ClientPreface => "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"u8; public const int MaxRequestHeaderFieldSize = 16 * 1024; public static readonly string FourKHeaderValue = new string('a', 4096); private static readonly Encoding HeaderValueEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); diff --git a/src/Shared/ServerInfrastructure/StringUtilities.cs b/src/Shared/ServerInfrastructure/StringUtilities.cs index ad361ddac0..9907c22afc 100644 --- a/src/Shared/ServerInfrastructure/StringUtilities.cs +++ b/src/Shared/ServerInfrastructure/StringUtilities.cs @@ -769,7 +769,7 @@ internal static class StringUtilities // This must be explicity typed as ReadOnlySpan<byte> // This then becomes a non-allocating mapping to the data section of the assembly. // If it is a var, Span<byte> or byte[], it allocates the byte array per call. - ReadOnlySpan<byte> hexEncodeMap = new byte[] { (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F' }; + ReadOnlySpan<byte> hexEncodeMap = "0123456789ABCDEF"; // Note: this only works with byte due to endian ambiguity for other types, // hence the later (char) casts diff --git a/src/SignalR/clients/csharp/Http.Connections.Client/src/Internal/ServerSentEventsMessageParser.cs b/src/SignalR/clients/csharp/Http.Connections.Client/src/Internal/ServerSentEventsMessageParser.cs index 95f9bc5bac..be8a8b2f5b 100644 --- a/src/SignalR/clients/csharp/Http.Connections.Client/src/Internal/ServerSentEventsMessageParser.cs +++ b/src/SignalR/clients/csharp/Http.Connections.Client/src/Internal/ServerSentEventsMessageParser.cs @@ -17,8 +17,8 @@ internal class ServerSentEventsMessageParser private const byte ByteColon = (byte)':'; // This uses C# compiler's ability to refer to static data directly. For more information see https://vcsjones.dev/2019/02/01/csharp-readonly-span-bytes-static - private static ReadOnlySpan<byte> DataPrefix => new byte[] { (byte)'d', (byte)'a', (byte)'t', (byte)'a', (byte)':', (byte)' ' }; - private static ReadOnlySpan<byte> SseLineEnding => new byte[] { (byte)'\r', (byte)'\n' }; + private static ReadOnlySpan<byte> DataPrefix => "data: "u8; + private static ReadOnlySpan<byte> SseLineEnding => "\r\n"u8; private static readonly byte[] _newLine = Encoding.UTF8.GetBytes(Environment.NewLine); private InternalParseState _internalParserState = InternalParseState.ReadMessagePayload; diff --git a/src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs b/src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs index 11cbfa1640..72b6838753 100644 --- a/src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs +++ b/src/SignalR/common/Http.Connections.Common/src/NegotiateProtocol.cs @@ -37,7 +37,7 @@ public static class NegotiateProtocol // Use C#7.3's ReadOnlySpan<byte> optimization for static data https://vcsjones.com/2019/02/01/csharp-readonly-span-bytes-static/ // Used to detect ASP.NET SignalR Server connection attempt - private static ReadOnlySpan<byte> ProtocolVersionPropertyNameBytes => new byte[] { (byte)'P', (byte)'r', (byte)'o', (byte)'t', (byte)'o', (byte)'c', (byte)'o', (byte)'l', (byte)'V', (byte)'e', (byte)'r', (byte)'s', (byte)'i', (byte)'o', (byte)'n' }; + private static ReadOnlySpan<byte> ProtocolVersionPropertyNameBytes => "ProtocolVersion"u8; /// <summary> /// Writes the <paramref name="response"/> to the <paramref name="output"/>. |