Skip to content

Commit 5494cdb

Browse files
committed
unsafe
1 parent e718b11 commit 5494cdb

File tree

6 files changed

+41
-50
lines changed

6 files changed

+41
-50
lines changed

src/Servers/Kestrel/Core/src/Internal/Http/HttpHeaders.Generated.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7481,7 +7481,7 @@ internal void ClearPseudoRequestHeaders()
74817481
}
74827482

74837483
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7484-
internal static unsafe ushort ReadUnalignedLittleEndian_ushort(ref byte source)
7484+
internal static ushort ReadUnalignedLittleEndian_ushort(ref byte source)
74857485
{
74867486
ushort result = Unsafe.ReadUnaligned<ushort>(ref source);
74877487
if (!BitConverter.IsLittleEndian)
@@ -7491,7 +7491,7 @@ internal static unsafe ushort ReadUnalignedLittleEndian_ushort(ref byte source)
74917491
return result;
74927492
}
74937493
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7494-
internal static unsafe uint ReadUnalignedLittleEndian_uint(ref byte source)
7494+
internal static uint ReadUnalignedLittleEndian_uint(ref byte source)
74957495
{
74967496
uint result = Unsafe.ReadUnaligned<uint>(ref source);
74977497
if (!BitConverter.IsLittleEndian)
@@ -7501,7 +7501,7 @@ internal static unsafe uint ReadUnalignedLittleEndian_uint(ref byte source)
75017501
return result;
75027502
}
75037503
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7504-
internal static unsafe ulong ReadUnalignedLittleEndian_ulong(ref byte source)
7504+
internal static ulong ReadUnalignedLittleEndian_ulong(ref byte source)
75057505
{
75067506
ulong result = Unsafe.ReadUnaligned<ulong>(ref source);
75077507
if (!BitConverter.IsLittleEndian)
@@ -7511,11 +7511,11 @@ internal static unsafe ulong ReadUnalignedLittleEndian_ulong(ref byte source)
75117511
return result;
75127512
}
75137513
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
7514-
public unsafe void Append(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value, bool checkForNewlineChars)
7514+
public void Append(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value, bool checkForNewlineChars)
75157515
{
75167516
ref byte nameStart = ref MemoryMarshal.GetReference(name);
75177517
var nameStr = string.Empty;
7518-
ref StringValues values = ref Unsafe.AsRef<StringValues>(null);
7518+
ref StringValues values = ref Unsafe.NullRef<StringValues>();
75197519
var flag = 0L;
75207520

75217521
// Does the name match any "known" headers
@@ -7924,9 +7924,9 @@ public unsafe void Append(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value, boo
79247924
}
79257925

79267926
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
7927-
public unsafe bool TryHPackAppend(int index, ReadOnlySpan<byte> value, bool checkForNewlineChars)
7927+
public bool TryHPackAppend(int index, ReadOnlySpan<byte> value, bool checkForNewlineChars)
79287928
{
7929-
ref StringValues values = ref Unsafe.AsRef<StringValues>(null);
7929+
ref StringValues values = ref Unsafe.NullRef<StringValues>();
79307930
var nameStr = string.Empty;
79317931
var flag = 0L;
79327932

@@ -8136,9 +8136,9 @@ public unsafe bool TryHPackAppend(int index, ReadOnlySpan<byte> value, bool chec
81368136
}
81378137

81388138
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
8139-
public unsafe bool TryQPackAppend(int index, ReadOnlySpan<byte> value, bool checkForNewlineChars)
8139+
public bool TryQPackAppend(int index, ReadOnlySpan<byte> value, bool checkForNewlineChars)
81408140
{
8141-
ref StringValues values = ref Unsafe.AsRef<StringValues>(null);
8141+
ref StringValues values = ref Unsafe.NullRef<StringValues>();
81428142
var nameStr = string.Empty;
81438143
var flag = 0L;
81448144

@@ -14806,7 +14806,7 @@ internal void ClearInvalidH2H3Headers()
1480614806
{
1480714807
_bits &= ~13161725953;
1480814808
}
14809-
internal unsafe void CopyToFast(ref BufferWriter<PipeWriter> output)
14809+
internal void CopyToFast(ref BufferWriter<PipeWriter> output)
1481014810
{
1481114811
var tempBits = (ulong)_bits;
1481214812
// Set exact next
@@ -14823,7 +14823,7 @@ internal unsafe void CopyToFast(ref BufferWriter<PipeWriter> output)
1482314823
return;
1482414824
}
1482514825

14826-
ref readonly StringValues values = ref Unsafe.AsRef<StringValues>(null);
14826+
ref readonly StringValues values = ref Unsafe.NullRef<StringValues>();
1482714827
do
1482814828
{
1482914829
int keyStart;
@@ -17629,4 +17629,4 @@ public bool MoveNext()
1762917629
}
1763017630
}
1763117631
}
17632-
}
17632+
}

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,25 +54,27 @@ internal HttpParser(bool showErrorDetails, bool disableHttp1LineFeedTerminators)
5454
private const byte ByteQuestionMark = (byte)'?';
5555
private const byte BytePercentage = (byte)'%';
5656
private const int MinTlsRequestSize = 1; // We need at least 1 byte to check for a proper TLS request line
57-
private static ReadOnlySpan<byte> RequestLineDelimeters => new byte[] { ByteLF, 0 };
57+
private static ReadOnlySpan<byte> RequestLineDelimiters => new byte[] { ByteLF, 0 };
5858

5959
/// <summary>
6060
/// This API supports framework infrastructure and is not intended to be used
6161
/// directly from application code.
6262
/// </summary>
6363
public bool ParseRequestLine(TRequestHandler handler, ref SequenceReader<byte> reader)
6464
{
65-
// Find the next delimeter.
66-
if (!reader.TryReadToAny(out ReadOnlySpan<byte> requestLine, RequestLineDelimeters, advancePastDelimiter: false))
65+
// Find the next delimiter.
66+
if (!reader.TryReadToAny(out ReadOnlySpan<byte> requestLine, RequestLineDelimiters, advancePastDelimiter: false))
6767
{
6868
return false;
6969
}
7070

7171
// Consume the delimiter.
7272
var foundDelimiter = reader.TryRead(out var next);
7373
Debug.Assert(foundDelimiter);
74+
// If null character found, or request line is empty
7475
if (next == 0 || requestLine.Length == 0)
7576
{
77+
// Rewind and re-read to format error message correctly
7678
reader.Rewind(requestLine.Length + 1);
7779
var readResult = reader.TryReadExact(requestLine.Length + 1, out var requestLineSequence);
7880
Debug.Assert(readResult);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ private bool AddValueUnknown(string key, StringValues value)
147147
}
148148

149149
[MethodImpl(MethodImplOptions.NoInlining)]
150-
private unsafe void AppendUnknownHeaders(string name, string valueString)
150+
private void AppendUnknownHeaders(string name, string valueString)
151151
{
152152
name = GetInternedHeaderName(name);
153153
Unknown.TryGetValue(name, out var existing);

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
5-
64
using System.Buffers;
75
using System.Buffers.Binary;
86
using System.Diagnostics;
@@ -31,6 +29,8 @@ internal static partial class HttpUtilities
3129

3230
private static readonly UTF8Encoding DefaultRequestHeaderEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
3331

32+
private static readonly SearchValues<char> _nullAndNewLineSearchValues = SearchValues.Create(['\r', '\n', '\0']);
33+
3434
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3535
private static void SetKnownMethod(ulong mask, ulong knownMethodUlong, HttpMethod knownMethod, int length)
3636
{
@@ -84,16 +84,16 @@ private static ulong GetMaskAsLong(ReadOnlySpan<byte> bytes)
8484

8585
// The same as GetAsciiStringNonNullCharacters but throws BadRequest
8686
[MethodImpl(MethodImplOptions.AggressiveInlining)]
87-
public static unsafe string GetHeaderName(this ReadOnlySpan<byte> span)
87+
public static string GetHeaderName(this ReadOnlySpan<byte> span)
8888
{
8989
if (span.IsEmpty)
9090
{
9191
return string.Empty;
9292
}
9393

94-
var str = string.Create(span.Length, (IntPtr)(&span), (destination, spanPtr) =>
94+
var str = string.Create(span.Length, span, (destination, spanPtr) =>
9595
{
96-
if (Ascii.ToUtf16(*(ReadOnlySpan<byte>*)spanPtr, destination, out _) != OperationStatus.Done)
96+
if (Ascii.ToUtf16(spanPtr, destination, out _) != OperationStatus.Done)
9797
{
9898
KestrelBadHttpRequestException.Throw(RequestRejectionReason.InvalidCharactersInHeaderName);
9999
}
@@ -128,7 +128,7 @@ public static string GetRequestHeaderString(this ReadOnlySpan<byte> span, string
128128
// New Line characters (CR, LF) are considered invalid at this point.
129129
// Null characters are also not allowed.
130130
var invalidCharIndex = checkForNewlineChars ?
131-
((ReadOnlySpan<char>)result).IndexOfAny('\r', '\n', '\0')
131+
((ReadOnlySpan<char>)result).IndexOfAny(_nullAndNewLineSearchValues)
132132
: ((ReadOnlySpan<char>)result).IndexOf('\0');
133133

134134
if (invalidCharIndex >= 0)

src/Servers/Kestrel/shared/KnownHeaders.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,7 +1213,7 @@ internal void ClearInvalidH2H3Headers()
12131213
{{
12141214
_bits &= ~{InvalidH2H3ResponseHeadersBits};
12151215
}}
1216-
internal unsafe void CopyToFast(ref BufferWriter<PipeWriter> output)
1216+
internal void CopyToFast(ref BufferWriter<PipeWriter> output)
12171217
{{
12181218
var tempBits = (ulong)_bits;
12191219
// Set exact next
@@ -1230,7 +1230,7 @@ internal unsafe void CopyToFast(ref BufferWriter<PipeWriter> output)
12301230
return;
12311231
}}
12321232
1233-
ref readonly StringValues values = ref Unsafe.AsRef<StringValues>(null);
1233+
ref readonly StringValues values = ref Unsafe.NullRef<StringValues>();
12341234
do
12351235
{{
12361236
int keyStart;
@@ -1303,7 +1303,7 @@ internal void ClearPseudoRequestHeaders()
13031303
}}
13041304
{Each(new string[] { "ushort", "uint", "ulong" }, type => $@"
13051305
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1306-
internal static unsafe {type} ReadUnalignedLittleEndian_{type}(ref byte source)
1306+
internal static {type} ReadUnalignedLittleEndian_{type}(ref byte source)
13071307
{{
13081308
{type} result = Unsafe.ReadUnaligned<{type}>(ref source);
13091309
if (!BitConverter.IsLittleEndian)
@@ -1313,11 +1313,11 @@ internal void ClearPseudoRequestHeaders()
13131313
return result;
13141314
}}")}
13151315
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
1316-
public unsafe void Append(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value, bool checkForNewlineChars)
1316+
public void Append(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value, bool checkForNewlineChars)
13171317
{{
13181318
ref byte nameStart = ref MemoryMarshal.GetReference(name);
13191319
var nameStr = string.Empty;
1320-
ref StringValues values = ref Unsafe.AsRef<StringValues>(null);
1320+
ref StringValues values = ref Unsafe.NullRef<StringValues>();
13211321
var flag = 0L;
13221322
13231323
// Does the name match any ""known"" headers
@@ -1339,9 +1339,9 @@ public unsafe void Append(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value, boo
13391339
}}
13401340
13411341
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
1342-
public unsafe bool TryHPackAppend(int index, ReadOnlySpan<byte> value, bool checkForNewlineChars)
1342+
public bool TryHPackAppend(int index, ReadOnlySpan<byte> value, bool checkForNewlineChars)
13431343
{{
1344-
ref StringValues values = ref Unsafe.AsRef<StringValues>(null);
1344+
ref StringValues values = ref Unsafe.NullRef<StringValues>();
13451345
var nameStr = string.Empty;
13461346
var flag = 0L;
13471347
@@ -1360,9 +1360,9 @@ public unsafe bool TryHPackAppend(int index, ReadOnlySpan<byte> value, bool chec
13601360
}}
13611361
13621362
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
1363-
public unsafe bool TryQPackAppend(int index, ReadOnlySpan<byte> value, bool checkForNewlineChars)
1363+
public bool TryQPackAppend(int index, ReadOnlySpan<byte> value, bool checkForNewlineChars)
13641364
{{
1365-
ref StringValues values = ref Unsafe.AsRef<StringValues>(null);
1365+
ref StringValues values = ref Unsafe.NullRef<StringValues>();
13661366
var nameStr = string.Empty;
13671367
var flag = 0L;
13681368

src/Shared/ServerInfrastructure/StringUtilities.cs

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,29 @@
33

44
using System.Buffers;
55
using System.Diagnostics;
6-
using System.Numerics;
76
using System.Runtime.CompilerServices;
87
using System.Runtime.InteropServices;
98
using System.Runtime.Intrinsics;
109
using System.Runtime.Intrinsics.X86;
1110
using System.Text;
1211

1312
#nullable enable
14-
#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
1513

1614
namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
1715

1816
internal static class StringUtilities
1917
{
20-
private static readonly SpanAction<char, (string? str, char separator, uint number)> s_populateSpanWithHexSuffix = PopulateSpanWithHexSuffix;
21-
2218
// Null checks must be done independently of this method (if required)
23-
public static unsafe string GetAsciiOrUTF8String(this ReadOnlySpan<byte> span, Encoding defaultEncoding)
19+
public static string GetAsciiOrUTF8String(this ReadOnlySpan<byte> span, Encoding defaultEncoding)
2420
{
2521
if (span.IsEmpty)
2622
{
2723
return string.Empty;
2824
}
2925

30-
var resultString = string.Create(span.Length, (IntPtr)(&span), (destination, spanPtr) =>
26+
var resultString = string.Create(span.Length, span, (destination, spanPtr) =>
3127
{
32-
if (Ascii.ToUtf16(*(ReadOnlySpan<byte>*)spanPtr, destination, out _) != OperationStatus.Done)
28+
if (Ascii.ToUtf16(spanPtr, destination, out _) != OperationStatus.Done)
3329
{
3430
// Mark resultString for UTF-8 encoding
3531
destination[0] = '\0';
@@ -53,19 +49,19 @@ public static unsafe string GetAsciiOrUTF8String(this ReadOnlySpan<byte> span, E
5349
}
5450

5551
// Null checks must be done independently of this method (if required)
56-
public static unsafe string GetAsciiString(this ReadOnlySpan<byte> span)
52+
public static string GetAsciiString(this ReadOnlySpan<byte> span)
5753
{
58-
return string.Create(span.Length, (IntPtr)(&span), (destination, spanPtr) =>
54+
return string.Create(span.Length, span, (destination, spanPtr) =>
5955
{
60-
if (Ascii.ToUtf16(*(ReadOnlySpan<byte>*)spanPtr, destination, out _) != OperationStatus.Done)
56+
if (Ascii.ToUtf16(spanPtr, destination, out _) != OperationStatus.Done)
6157
{
6258
throw new InvalidOperationException();
6359
}
6460
});
65-
};
61+
}
6662

6763
// Null checks must be done independently of this method (if required)
68-
public static unsafe string GetLatin1String(this ReadOnlySpan<byte> span)
64+
public static string GetLatin1String(this ReadOnlySpan<byte> span)
6965
{
7066
if (span.IsEmpty)
7167
{
@@ -196,11 +192,4 @@ ref Unsafe.Add(ref MemoryMarshal.GetReference(buffer), i)),
196192
buffer[0] = (char)hexEncodeMap[(number >> 28) & 0xF];
197193
}
198194
};
199-
200-
[MethodImpl(MethodImplOptions.AggressiveInlining)] // Needs a push
201-
private static bool CheckBytesInAsciiRange(Vector<sbyte> check)
202-
{
203-
// Vectorized byte range check, signed byte > 0 for 1-127
204-
return Vector.GreaterThanAll(check, Vector<sbyte>.Zero);
205-
}
206195
}

0 commit comments

Comments
 (0)