Skip to content

Commit 7f4a3ef

Browse files
ladeakladeakgfoidlamcasey
authored
Use SearchValues throughout dotnet/aspnetcore (part 2) (#54804)
* Using SearchValues in cookie header parser to find the end of the cookie value. * Apply suggestions from code review Co-authored-by: Günther Foidl <[email protected]> * Update src/Http/Shared/CookieHeaderParserShared.cs Co-authored-by: Andrew Casey <[email protected]> --------- Co-authored-by: ladeak <[email protected]> Co-authored-by: Günther Foidl <[email protected]> Co-authored-by: Andrew Casey <[email protected]>
1 parent 4e2e41d commit 7f4a3ef

File tree

2 files changed

+32
-20
lines changed

2 files changed

+32
-20
lines changed

src/Http/Http/test/RequestCookiesCollectionTests.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,12 @@ public void ParseManyCookies()
3737
[InlineData("er=dd,err=cc,errr=bb", new[] { "dd", "cc", "bb" })]
3838
[InlineData("errorcookie=dd,:(\"sa;", new[] { "dd" })]
3939
[InlineData("s;", null)]
40+
[InlineData("er=;,err=,errr=\\,errrr=\"", null)]
4041
public void ParseInvalidCookies(string cookieToParse, string[] expectedCookieValues)
4142
{
4243
var cookies = RequestCookieCollection.Parse(new StringValues(new[] { cookieToParse }));
4344

44-
if(expectedCookieValues == null)
45+
if (expectedCookieValues == null)
4546
{
4647
Assert.Equal(0, cookies.Count);
4748
return;
@@ -54,4 +55,21 @@ public void ParseInvalidCookies(string cookieToParse, string[] expectedCookieVal
5455
Assert.Equal(value, cookies.ElementAt(i).Value);
5556
}
5657
}
58+
59+
[Fact]
60+
public void AllExpectedCookieValueCharsPresent()
61+
{
62+
foreach (var c in Enumerable.Range(0x00, 0xFF).Select(x => (char)x))
63+
{
64+
var cookies = RequestCookieCollection.Parse(new StringValues(new[] { $"something={c}" }));
65+
if (c < 0x21 || c > 0x7E || c == '\\' || c == ',' || c == ';' || c == '\"')
66+
{
67+
Assert.Equal(0, cookies.Count);
68+
}
69+
else
70+
{
71+
Assert.Equal(c.ToString(), cookies.Single().Value);
72+
}
73+
}
74+
}
5775
}

src/Http/Shared/CookieHeaderParserShared.cs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
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+
using System.Buffers;
45
using System.Diagnostics.CodeAnalysis;
56
using System.Diagnostics.Contracts;
67
using Microsoft.Extensions.Primitives;
@@ -9,6 +10,11 @@ namespace Microsoft.Net.Http.Headers;
910

1011
internal static class CookieHeaderParserShared
1112
{
13+
// cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
14+
// ; US-ASCII characters excluding CTLs, whitespace, DQUOTE, comma, semicolon, and backslash
15+
private static readonly SearchValues<char> CookieValueChar =
16+
SearchValues.Create("!#$%&'()*+-./0123456789:<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~");
17+
1218
public static bool TryParseValues(StringValues values, IDictionary<string, string> store, bool supportsMultipleValues)
1319
{
1420
// If a parser returns an empty list, it means there was no value, but that's valid (e.g. "Accept: "). The caller
@@ -192,15 +198,14 @@ internal static StringSegment GetCookieValue(StringSegment input, ref int offset
192198
offset++;
193199
}
194200

195-
while (offset < input.Length)
201+
var delta = input.AsSpan(offset).IndexOfAnyExcept(CookieValueChar);
202+
if (delta < 0)
196203
{
197-
var c = input[offset];
198-
if (!IsCookieValueChar(c))
199-
{
200-
break;
201-
}
202-
203-
offset++;
204+
offset = input.Length;
205+
}
206+
else
207+
{
208+
offset += delta;
204209
}
205210

206211
if (inQuotes)
@@ -232,15 +237,4 @@ private static bool ReadEqualsSign(StringSegment input, ref int offset)
232237
offset++;
233238
return true;
234239
}
235-
236-
// cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
237-
// ; US-ASCII characters excluding CTLs, whitespace DQUOTE, comma, semicolon, and backslash
238-
private static bool IsCookieValueChar(char c)
239-
{
240-
if (c < 0x21 || c > 0x7E)
241-
{
242-
return false;
243-
}
244-
return !(c == '"' || c == ',' || c == ';' || c == '\\');
245-
}
246240
}

0 commit comments

Comments
 (0)