diff --git a/src/libraries/Common/src/System/IO/Archiving.Utils.Windows.cs b/src/libraries/Common/src/System/IO/Archiving.Utils.Windows.cs index beceebc560436..73eddcca7eac1 100644 --- a/src/libraries/Common/src/System/IO/Archiving.Utils.Windows.cs +++ b/src/libraries/Common/src/System/IO/Archiving.Utils.Windows.cs @@ -1,47 +1,45 @@ // 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.Runtime.InteropServices; -using System.Text; namespace System.IO { internal static partial class ArchivingUtils { + private static readonly IndexOfAnyValues s_illegalChars = IndexOfAnyValues.Create( + "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000A\u000B\u000C\u000D\u000E\u000F" + + "\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\u001B\u001C\u001D\u001E\u001F" + + "\"*:<>?|"); + internal static string SanitizeEntryFilePath(string entryPath) { // Find the first illegal character in the entry path. - for (int i = 0; i < entryPath.Length; i++) + int i = entryPath.AsSpan().IndexOfAny(s_illegalChars); + if (i < 0) { - switch (entryPath[i]) - { - // We found at least one character that needs to be replaced. - case < (char)32 or '?' or ':' or '*' or '"' or '<' or '>' or '|': - return string.Create(entryPath.Length, (i, entryPath), (dest, state) => - { - string entryPath = state.entryPath; + // There weren't any characters to sanitize. Just return the original string. + return entryPath; + } + + // We found at least one character that needs to be replaced. + return string.Create(entryPath.Length, (i, entryPath), static (dest, state) => + { + string entryPath = state.entryPath; - // Copy over to the new string everything until the character, then - // substitute for the found character. - entryPath.AsSpan(0, state.i).CopyTo(dest); - dest[state.i] = '_'; + // Copy over to the new string everything until the character, then + // substitute for the found character. + entryPath.AsSpan(0, state.i).CopyTo(dest); + dest[state.i] = '_'; - // Continue looking for and replacing any more illegal characters. - for (int i = state.i + 1; i < entryPath.Length; i++) - { - char c = entryPath[i]; - dest[i] = c switch - { - < (char)32 or '?' or ':' or '*' or '"' or '<' or '>' or '|' => '_', - _ => c, - }; - } - }); + // Continue looking for and replacing any more illegal characters. + for (int i = state.i + 1; i < entryPath.Length; i++) + { + char c = entryPath[i]; + dest[i] = s_illegalChars.Contains(c) ? '_' : c; } - } - - // There weren't any characters to sanitize. Just return the original string. - return entryPath; + }); } public static unsafe string EntryFromPath(ReadOnlySpan path, bool appendPathSeparator = false)