Fix stdio client transport CLI argument escaping. (#811)

* Fix stdio client transport CLI argument escaping.

* Fix failing Windows test.

* Add more test cases and refine escaping logic.

* Fix test failures in mono

* Style fixes

* Tweak stdio test

* Tweak tests further
This commit is contained in:
Eirik Tsarpalis 2025-09-25 14:46:39 +03:00 • committed by GitHub
commit d8768de302
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -90,13 +90,13 @@ public sealed partial class StdioClientTransport : IClientTransport
#if NET
foreach (string arg in arguments)
{
startInfo.ArgumentList.Add(arg);
startInfo.ArgumentList.Add(EscapeArgumentString(arg));
}
#else
StringBuilder argsBuilder = new();
foreach (string arg in arguments)
{
PasteArguments.AppendArgument(argsBuilder, arg);
PasteArguments.AppendArgument(argsBuilder, EscapeArgumentString(arg));
}
startInfo.Arguments = argsBuilder.ToString();
@ -236,6 +236,26 @@ public sealed partial class StdioClientTransport : IClientTransport
}
}
private static string EscapeArgumentString(string argument) =>
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && !ContainsWhitespaceRegex.IsMatch(argument) ?
WindowsCliSpecialArgumentsRegex.Replace(argument, static match => "^" + match.Value) :
argument;
private const string WindowsCliSpecialArgumentsRegexString = "[&^><|]";
#if NET
private static Regex WindowsCliSpecialArgumentsRegex => GetWindowsCliSpecialArgumentsRegex();
private static Regex ContainsWhitespaceRegex => GetContainsWhitespaceRegex();
[GeneratedRegex(WindowsCliSpecialArgumentsRegexString, RegexOptions.CultureInvariant)]
private static partial Regex GetWindowsCliSpecialArgumentsRegex();
[GeneratedRegex(@"\s", RegexOptions.CultureInvariant)]
private static partial Regex GetContainsWhitespaceRegex();
#else
private static Regex WindowsCliSpecialArgumentsRegex { get; } = new(WindowsCliSpecialArgumentsRegexString, RegexOptions.Compiled | RegexOptions.CultureInvariant);
private static Regex ContainsWhitespaceRegex { get; } = new(@"\s", RegexOptions.Compiled | RegexOptions.CultureInvariant);
#endif
[LoggerMessage(Level = LogLevel.Information, Message = "{EndpointName} connecting.")]
private static partial void LogTransportConnecting(ILogger logger, string endpointName);