Repository: dotnet/runtime
File: src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs (C#)

Code before:

            if (expression is not null)
            {
                // We need to ensure that the expression is prepped to be used as an NtQueryDirectoryFile filter.
                // If the match type is simple, we need to escape the special DOS wildcard characters. If it is
                // DOS style, the characters have already been escaped in the FileSystemEnumerableFactory.

                if (expression.Length > 255 || expression == "*")
                {
                    // Don't allow expressions longer than the maximum filename length. This comes back as
                    // STATUS_INVALID_PARAMETER from NtQueryDirectoryFile. We could catch that there, but
                    // don't want to mask other bad parameter issues.
                    //
                    // Also, an expression of "*" is pointless as a filter- it matches everything. "*.*"
                    // should have been converted to "*" already in the case of MatchType.Win32.
                    expression = null;
                }
                else if (_options.MatchType == MatchType.Simple && expression.AsSpan().ContainsAny(@"\""<>"))
                {
                    // Escape the escaping literal first
                    expression = expression.Replace("\\", "\\\\");

                    // Also need to escape the other special wild characters ('"', '<', and '>')
                    expression = expression.Replace("\"", "\\\"");
                    expression = expression.Replace(">", "\\>");
                    expression = expression.Replace("<", "\\<");
                }
            }

            _expression = expression;
        }

        private void Init()
        {
            // We'll only suppress the media insertion prompt on the topmost directory as that is the
            // most likely scenario and we don't want to take the perf hit for large enumerations.
            // (We weren't consistent with how we handled this historically.)
            using (default(DisableMediaInsertionPrompt))
            {
                // We need to initialize the directory handle up front to ensure
                // we immediately throw IO exceptions for missing directory/etc.
                _directoryHandle = CreateDirectoryHandle(_rootDirectory);
                if (_directoryHandle == IntPtr.Zero)
                    _lastEntryFound = true;
            }

            _currentPath = _rootDirectory;

            int requestedBufferSize = _options.BufferSize;
            _bufferLength = requestedBufferSize <= 0 ? StandardBufferSize
                : Math.Max(MinimumBufferSize, requestedBufferSize);

Review comment (security):
This could incur up to four additional string allocations. Could we get that down to just one with something like:
```csharp
else if (_options.MatchType == MatchType.Simple)
{
    ReadOnlySpan<char> span = expression;
    ReadOnlySpan<char> charsToEscape = ['\\', '"', '<', '>'];
    int i = span.IndexOfAny(charsToEscape);
    if (i >= 0)
    {
        ValueStringBuilder vsb = new(stackalloc char[256]);
        do
        {
            vsb.Append(span.Slice(0, i));
            vsb.Append('\\');
            vsb.Append(span[i]);
            span = span.Slice(i + 1);
            i = span.IndexOfAny(charsToEscape);
        }
        while (i >= 0);

        vsb.Append(span);
        expression = vsb.ToString();
    }
}
```
The charsToEscape could also be put into a static readonly SearchValues if it would result in a measurable improvement.

Code after:
            else if (expression is not null)
            {
                // We need to ensure that the expression is prepped to be used as an NtQueryDirectoryFile filter.
                // If the match type is simple, we need to escape the special DOS wildcard characters. If it is
                // DOS style, the characters have already been escaped in the FileSystemEnumerableFactory.

                if (expression.Length > 255 || expression is "*" or "." or "..")
                {
                    // Don't allow expressions longer than the maximum filename length. This comes back as
                    // STATUS_INVALID_PARAMETER from NtQueryDirectoryFile. We could catch that there, but
                    // don't want to mask other bad parameter issues.
                    //
                    // Also, an expression of "*" is pointless as a filter- it matches everything. "*.*"
                    // should have been converted to "*" already in the case of MatchType.Win32.
                    //
                    // Finally, "." and ".." are invalid filter names on their own, but we allow you to see
                    // these entries if you specifically ask via EnumerationOptions.ReturnSpecialDirectories.
                    expression = null;
                }
                else if (_options.MatchType == MatchType.Simple)
                {
                    expression = FileSystemName.EscapeExpression(expression);
                }
            }

            _expression = expression;
        }

        private void Init()
        {
            // We'll only suppress the media insertion prompt on the topmost directory as that is the
            // most likely scenario and we don't want to take the perf hit for large enumerations.
            // (We weren't consistent with how we handled this historically.)
            using (default(DisableMediaInsertionPrompt))
            {
                // We need to initialize the directory handle up front to ensure
                // we immediately throw IO exceptions for missing directory/etc.
                _directoryHandle = CreateDirectoryHandle(_rootDirectory);
                if (_directoryHandle == IntPtr.Zero)
                    _lastEntryFound = true;
            }

            _currentPath = _rootDirectory;

            int requestedBufferSize = _options.BufferSize;
            _bufferLength = requestedBufferSize <= 0 ? StandardBufferSize
                : Math.Max(MinimumBufferSize, requestedBufferSize);

            try
            {
                // NtQueryDirectoryFile needs its buffer to be 64bit aligned to work