From d7a7e3484f8feaf3704482eaa18b6e45fe847c1c Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Wed, 1 Feb 2023 17:54:07 -0500 Subject: [PATCH] Use IndexOfAnyValues in MailBnfHelper (#81486) --- .../src/System/Net/Mail/MailBnfHelper.cs | 83 +++++++--------------- 1 file changed, 27 insertions(+), 56 deletions(-) diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailBnfHelper.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailBnfHelper.cs index 9ce43f2..cc75fb5 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailBnfHelper.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailBnfHelper.cs @@ -1,6 +1,7 @@ // 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.Text; @@ -17,15 +18,17 @@ namespace System.Net.Mime // characters allowed in domain literals internal static readonly bool[] Dtext = CreateCharactersAllowedInDomainLiterals(); - // characters allowed in header names - internal static readonly bool[] Ftext = CreateCharactersAllowedInHeaderNames(); - - // characters allowed in tokens - internal static readonly bool[] Ttext = CreateCharactersAllowedInTokens(); - // characters allowed inside of comments internal static readonly bool[] Ctext = CreateCharactersAllowedInComments(); + private static readonly IndexOfAnyValues s_charactersAllowedInHeaderNames = + // ftext = %d33-57 / %d59-126 + IndexOfAnyValues.Create("!\"#$%&'()*+,-./0123456789;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"); + + private static readonly IndexOfAnyValues s_charactersAllowedInTokens = + // ttext = %d33-126 except '()<>@,;:\"/[]?=' + IndexOfAnyValues.Create("!#$%&'*+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~"); + internal const char Quote = '\"'; internal const char Space = ' '; internal const char Tab = '\t'; @@ -101,38 +104,6 @@ namespace System.Net.Mime return dtext; } - private static bool[] CreateCharactersAllowedInHeaderNames() - { - // ftext = %d33-57 / %d59-126 - var ftext = new bool[128]; - for (int i = 33; i <= 57; i++) { ftext[i] = true; } - for (int i = 59; i <= 126; i++) { ftext[i] = true; } - return ftext; - } - - private static bool[] CreateCharactersAllowedInTokens() - { - // ttext = %d33-126 except '()<>@,;:\"/[]?=' - var ttext = new bool[128]; - for (int i = 33; i <= 126; i++) { ttext[i] = true; } - ttext['('] = false; - ttext[')'] = false; - ttext['<'] = false; - ttext['>'] = false; - ttext['@'] = false; - ttext[','] = false; - ttext[';'] = false; - ttext[':'] = false; - ttext['\\'] = false; - ttext['"'] = false; - ttext['/'] = false; - ttext['['] = false; - ttext[']'] = false; - ttext['?'] = false; - ttext['='] = false; - return ttext; - } - private static bool[] CreateCharactersAllowedInComments() { // ctext- %d1-8 / %d11 / %d12 / %d14-31 / %33-39 / %42-91 / %93-127 @@ -175,14 +146,10 @@ namespace System.Net.Mime internal static void ValidateHeaderName(string data) { - int offset = 0; - for (; offset < data.Length; offset++) + if (data.Length == 0 || data.AsSpan().IndexOfAnyExcept(s_charactersAllowedInHeaderNames) >= 0) { - if (data[offset] > Ftext.Length || !Ftext[data[offset]]) - throw new FormatException(SR.InvalidHeaderName); - } - if (offset == 0) throw new FormatException(SR.InvalidHeaderName); + } } internal static string? ReadQuotedString(string data, ref int offset, StringBuilder? builder) @@ -253,24 +220,28 @@ namespace System.Net.Mime internal static string ReadToken(string data, ref int offset) { int start = offset; - for (; offset < data.Length; offset++) + + if (start >= data.Length) { - if (!Ascii.IsValid(data[offset])) - { - throw new FormatException(SR.Format(SR.MailHeaderFieldInvalidCharacter, data[offset])); - } - else if (!Ttext[data[offset]]) + return string.Empty; + } + + ReadOnlySpan span = data.AsSpan(start); + int i = span.IndexOfAnyExcept(s_charactersAllowedInTokens); + if (i >= 0) + { + if (i == 0 || !Ascii.IsValid(span[i])) { - break; + throw new FormatException(SR.Format(SR.MailHeaderFieldInvalidCharacter, span[i])); } } - - if (start == offset && offset < data.Length) + else { - throw new FormatException(SR.Format(SR.MailHeaderFieldInvalidCharacter, data[offset])); + i = span.Length; } - return data.Substring(start, offset - start); + offset += i; + return data.Substring(start, i); } private static readonly string?[] s_months = new string?[] { null, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; @@ -328,7 +299,7 @@ namespace System.Net.Mime continue; } - if (!Ttext[data[offset]] || data[offset] == ' ') + if (!s_charactersAllowedInTokens.Contains(data[offset]) || data[offset] == ' ') { builder.Append('"'); for (; offset < data.Length; offset++) -- 2.7.4