|
3 | 3 |
|
4 | 4 | using System.Buffers; |
5 | 5 | using System.Diagnostics; |
| 6 | +using System.Runtime.InteropServices; |
6 | 7 | using System.Text; |
7 | 8 |
|
8 | 9 | namespace System |
9 | 10 | { |
10 | 11 | internal static class PercentEncodingHelper |
11 | 12 | { |
12 | | - public static unsafe int UnescapePercentEncodedUTF8Sequence(char* input, int length, ref ValueStringBuilder dest, bool isQuery, bool iriParsing) |
| 13 | + public static int UnescapePercentEncodedUTF8Sequence(ReadOnlySpan<char> input, ref ValueStringBuilder dest, bool isQuery, bool iriParsing) |
13 | 14 | { |
| 15 | + int length = input.Length; |
14 | 16 | // The following assertions rely on the input not mutating mid-operation, as is the case currently since callers are working with strings |
15 | 17 | // If we start accepting input such as spans, this method must be audited to ensure no buffer overruns/infinite loops could occur |
16 | 18 |
|
@@ -85,15 +87,18 @@ public static unsafe int UnescapePercentEncodedUTF8Sequence(char* input, int len |
85 | 87 | Debug.Assert(bytesLeftInBuffer < 4 || (fourByteBuffer & (BitConverter.IsLittleEndian ? 0x80000000 : 0x00000080)) != 0); |
86 | 88 |
|
87 | 89 | uint temp = fourByteBuffer; // make a copy so that the *copy* (not the original) is marked address-taken |
88 | | - if (Rune.DecodeFromUtf8(new ReadOnlySpan<byte>(&temp, bytesLeftInBuffer), out Rune rune, out bytesConsumed) == OperationStatus.Done) |
| 90 | + |
| 91 | + |
| 92 | + |
| 93 | + if (Rune.DecodeFromUtf8(MemoryMarshal.AsBytes(new ReadOnlySpan<uint>(ref temp))[..bytesLeftInBuffer], out Rune rune, out bytesConsumed) == OperationStatus.Done) |
89 | 94 | { |
90 | 95 | Debug.Assert(bytesConsumed >= 2, $"Rune.DecodeFromUtf8 consumed {bytesConsumed} bytes, likely indicating input was modified concurrently during UnescapePercentEncodedUTF8Sequence's execution"); |
91 | 96 |
|
92 | 97 | if (!iriParsing || IriHelper.CheckIriUnicodeRange((uint)rune.Value, isQuery)) |
93 | 98 | { |
94 | 99 | if (charsToCopy != 0) |
95 | 100 | { |
96 | | - dest.Append(new ReadOnlySpan<char>(input + totalCharsConsumed - charsToCopy, charsToCopy)); |
| 101 | + dest.Append(input.Slice(totalCharsConsumed - charsToCopy, charsToCopy)); |
97 | 102 | charsToCopy = 0; |
98 | 103 | } |
99 | 104 |
|
@@ -167,7 +172,8 @@ public static unsafe int UnescapePercentEncodedUTF8Sequence(char* input, int len |
167 | 172 | return totalCharsConsumed; |
168 | 173 |
|
169 | 174 | bytesLeftInBuffer *= 3; |
170 | | - dest.Append(new ReadOnlySpan<char>(input + totalCharsConsumed - charsToCopy, charsToCopy + bytesLeftInBuffer)); |
| 175 | + |
| 176 | + dest.Append(input.Slice(totalCharsConsumed - charsToCopy, charsToCopy + bytesLeftInBuffer)); |
171 | 177 | return totalCharsConsumed + bytesLeftInBuffer; |
172 | 178 | } |
173 | 179 | } |
|
0 commit comments