Skip to content

Commit 350cf6b

Browse files
authored
SkipLocalsInit on methods with stackalloc (#32567)
* SkipLocalsInit on Kestrel methods with stackalloc * Clean up * Fixes * Fix tests * PR feedback
1 parent badf48e commit 350cf6b

File tree

11 files changed

+22
-6
lines changed

11 files changed

+22
-6
lines changed

src/DataProtection/Abstractions/src/Microsoft.AspNetCore.DataProtection.Abstractions.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Microsoft.AspNetCore.DataProtection.IDataProtectionProvider
77
Microsoft.AspNetCore.DataProtection.IDataProtector</Description>
88
<TargetFrameworks>$(DefaultNetFxTargetFramework);netstandard2.0;$(DefaultNetCoreTargetFramework)</TargetFrameworks>
99
<IsAspNetCoreApp>true</IsAspNetCoreApp>
10+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
1011
<GenerateDocumentationFile>true</GenerateDocumentationFile>
1112
<PackageTags>aspnetcore;dataprotection</PackageTags>
1213
<Nullable>enable</Nullable>

src/Http/Routing/src/Matching/DfaMatcher.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Runtime.CompilerServices;
67
using System.Threading.Tasks;
78
using Microsoft.AspNetCore.Http;
89
using Microsoft.AspNetCore.Routing.Patterns;
@@ -27,6 +28,7 @@ public DfaMatcher(ILogger<DfaMatcher> logger, EndpointSelector selector, DfaStat
2728
_isDefaultEndpointSelector = selector is DefaultEndpointSelector;
2829
}
2930

31+
[SkipLocalsInit]
3032
public sealed override Task MatchAsync(HttpContext httpContext)
3133
{
3234
if (httpContext == null)

src/Http/Routing/src/Microsoft.AspNetCore.Routing.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Microsoft.AspNetCore.Routing.Route
77
Microsoft.AspNetCore.Routing.RouteCollection</Description>
88
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
99
<IsAspNetCoreApp>true</IsAspNetCoreApp>
10+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
1011
<GenerateDocumentationFile>true</GenerateDocumentationFile>
1112
<PackageTags>aspnetcore;routing</PackageTags>
1213
<IsPackable>false</IsPackable>

src/Http/WebUtilities/src/FormPipeReader.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ private void ThrowValueTooLargeException()
332332
throw new InvalidDataException($"Form value length limit {ValueLengthLimit} exceeded.");
333333
}
334334

335+
[SkipLocalsInit]
335336
private string GetDecodedStringFromReadOnlySequence(in ReadOnlySequence<byte> ros)
336337
{
337338
if (ros.IsSingleSegment)
@@ -341,7 +342,7 @@ private string GetDecodedStringFromReadOnlySequence(in ReadOnlySequence<byte> ro
341342

342343
if (ros.Length < StackAllocThreshold)
343344
{
344-
Span<byte> buffer = stackalloc byte[(int)ros.Length];
345+
Span<byte> buffer = stackalloc byte[StackAllocThreshold].Slice(0, (int)ros.Length);
345346
ros.CopyTo(buffer);
346347
return GetDecodedString(buffer);
347348
}

src/Http/WebUtilities/src/Microsoft.AspNetCore.WebUtilities.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
66
<IsAspNetCoreApp>true</IsAspNetCoreApp>
77
<DefineConstants>$(DefineConstants);WebEncoders_In_WebUtilities</DefineConstants>
8+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
89
<GenerateDocumentationFile>true</GenerateDocumentationFile>
910
<PackageTags>aspnetcore</PackageTags>
1011
<IsPackable>false</IsPackable>

src/Servers/Kestrel/Core/src/Internal/Http/HttpRequestHeaders.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ private void AppendContentLength(ReadOnlySpan<byte> value)
9696
}
9797

9898
[MethodImpl(MethodImplOptions.NoInlining)]
99+
[SkipLocalsInit]
99100
private void AppendContentLengthCustomEncoding(ReadOnlySpan<byte> value, Encoding? customEncoding)
100101
{
101102
if (_contentLength.HasValue)

src/Servers/Kestrel/Core/src/Internal/Http2/Http2Stream.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,10 +352,11 @@ private bool TryValidateAuthorityAndHost(out string hostText)
352352
return true;
353353
}
354354

355+
[SkipLocalsInit]
355356
private bool TryValidatePath(ReadOnlySpan<char> pathSegment)
356357
{
357358
// Must start with a leading slash
358-
if (pathSegment.Length == 0 || pathSegment[0] != '/')
359+
if (pathSegment.IsEmpty || pathSegment[0] != '/')
359360
{
360361
ResetAndAbort(new ConnectionAbortedException(CoreStrings.FormatHttp2StreamErrorPathInvalid(RawTarget)), Http2ErrorCode.PROTOCOL_ERROR);
361362
return false;

src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.IO.Pipelines;
88
using System.Net.Http;
99
using System.Net.Http.QPack;
10+
using System.Runtime.CompilerServices;
1011
using System.Threading;
1112
using System.Threading.Tasks;
1213
using Microsoft.AspNetCore.Connections;
@@ -739,10 +740,11 @@ private bool TryValidateAuthorityAndHost(out string hostText)
739740
return true;
740741
}
741742

743+
[SkipLocalsInit]
742744
private bool TryValidatePath(ReadOnlySpan<char> pathSegment)
743745
{
744746
// Must start with a leading slash
745-
if (pathSegment.Length == 0 || pathSegment[0] != '/')
747+
if (pathSegment.IsEmpty || pathSegment[0] != '/')
746748
{
747749
Abort(new ConnectionAbortedException(CoreStrings.FormatHttp3StreamErrorPathInvalid(RawTarget)), Http3ErrorCode.ProtocolError);
748750
return false;

src/Servers/Kestrel/Core/src/Internal/Infrastructure/KestrelEventSource.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ protected override void OnEventCommand(EventCommandEventArgs command)
301301
}
302302

303303
[NonEvent]
304+
[SkipLocalsInit]
304305
private unsafe void WriteEvent(int eventId, string? arg1, string? arg2, string? arg3, string? arg4, string? arg5)
305306
{
306307
const int EventDataCount = 5;

src/Shared/WebEncoders/WebEncoders.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#endif
99
using System.Diagnostics;
1010
using System.Globalization;
11+
using System.Runtime.CompilerServices;
1112
using Microsoft.Extensions.WebEncoders.Sources;
1213

1314
#if WebEncoders_In_WebUtilities
@@ -343,8 +344,11 @@ public static int GetArraySizeRequiredToEncode(int count)
343344
/// </summary>
344345
/// <param name="input">The binary input to encode.</param>
345346
/// <returns>The base64url-encoded form of <paramref name="input"/>.</returns>
347+
[SkipLocalsInit]
346348
public static string Base64UrlEncode(ReadOnlySpan<byte> input)
347349
{
350+
const int StackAllocThreshold = 128;
351+
348352
if (input.IsEmpty)
349353
{
350354
return string.Empty;
@@ -353,8 +357,8 @@ public static string Base64UrlEncode(ReadOnlySpan<byte> input)
353357
int bufferSize = GetArraySizeRequiredToEncode(input.Length);
354358

355359
char[]? bufferToReturnToPool = null;
356-
Span<char> buffer = bufferSize <= 128
357-
? stackalloc char[bufferSize]
360+
Span<char> buffer = bufferSize <= StackAllocThreshold
361+
? stackalloc char[StackAllocThreshold]
358362
: bufferToReturnToPool = ArrayPool<char>.Shared.Rent(bufferSize);
359363

360364
var numBase64Chars = Base64UrlEncode(input, buffer);

src/SignalR/common/Http.Connections/src/Microsoft.AspNetCore.Http.Connections.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<Description>Components for providing real-time bi-directional communication across the Web.</Description>
55
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
66
<IsAspNetCoreApp>true</IsAspNetCoreApp>
7+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
78
<IsPackable>false</IsPackable>
89
<Nullable>enable</Nullable>
910
</PropertyGroup>

0 commit comments

Comments
 (0)