Skip to content

Commit

Permalink
Use IndexOfAnyValues in WebSocketValidate (dotnet#79974)
Browse files Browse the repository at this point in the history
  • Loading branch information
MihaZupan committed Jan 2, 2023
1 parent b81b822 commit d354d3c
Showing 1 changed file with 15 additions and 32 deletions.
47 changes: 15 additions & 32 deletions src/libraries/Common/src/System/Net/WebSockets/WebSocketValidate.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Buffers;
using System.Diagnostics;
using System.Globalization;
using System.Text;

namespace System.Net.WebSockets
Expand All @@ -27,7 +27,10 @@ internal static partial class WebSocketValidate
private const int CloseStatusCodeFailedTLSHandshake = 1015;
private const int InvalidCloseStatusCodesFrom = 0;
private const int InvalidCloseStatusCodesTo = 999;
private const string Separators = "()<>@,;:\\\"/[]?={} ";

// [0x21, 0x7E] except separators "()<>@,;:\\\"/[]?={} ".
private static readonly IndexOfAnyValues<char> s_validSubprotocolChars =
IndexOfAnyValues.Create("!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz|~");

internal static void ThrowIfInvalidState(WebSocketState currentState, bool isDisposed, WebSocketState[] validStates)
{
Expand Down Expand Up @@ -60,32 +63,16 @@ internal static void ValidateSubprotocol(string subProtocol)
throw new ArgumentException(SR.net_WebSockets_InvalidEmptySubProtocol, nameof(subProtocol));
}

string? invalidChar = null;
int i = 0;
while (i < subProtocol.Length)
int indexOfInvalidChar = subProtocol.AsSpan().IndexOfAnyExcept(s_validSubprotocolChars);
if (indexOfInvalidChar >= 0)
{
char ch = subProtocol[i];
if (ch < 0x21 || ch > 0x7e)
{
invalidChar = $"[{(int)ch}]";
break;
}
char invalidChar = subProtocol[indexOfInvalidChar];

if (!char.IsLetterOrDigit(ch) &&
#pragma warning disable CA2249 // Consider using 'string.Contains' instead of 'string.IndexOf'. This file is built into a project that doesn't have string.Contains(char).
Separators.IndexOf(ch) >= 0)
#pragma warning restore CA2249
{
invalidChar = ch.ToString();
break;
}
string invalidCharDescription = char.IsBetween(invalidChar, (char)0x21, (char)0x7E)
? invalidChar.ToString() // ASCII separator
: $"[{(int)invalidChar}]";

i++;
}

if (invalidChar != null)
{
throw new ArgumentException(SR.Format(SR.net_WebSockets_InvalidCharInProtocolString, subProtocol, invalidChar), nameof(subProtocol));
throw new ArgumentException(SR.Format(SR.net_WebSockets_InvalidCharInProtocolString, subProtocol, invalidCharDescription), nameof(subProtocol));
}
}

Expand All @@ -112,13 +99,9 @@ internal static void ValidateCloseStatus(WebSocketCloseStatus closeStatus, strin
nameof(closeStatus));
}

int length = 0;
if (!string.IsNullOrEmpty(statusDescription))
{
length = Encoding.UTF8.GetByteCount(statusDescription);
}

if (length > MaxControlFramePayloadLength)
if (!string.IsNullOrEmpty(statusDescription) &&
Encoding.UTF8.GetMaxByteCount(statusDescription.Length) > MaxControlFramePayloadLength &&
Encoding.UTF8.GetByteCount(statusDescription) > MaxControlFramePayloadLength)
{
throw new ArgumentException(SR.Format(SR.net_WebSockets_InvalidCloseStatusDescription,
statusDescription,
Expand Down

0 comments on commit d354d3c

Please sign in to comment.