`TProcess.Parameters` acts differently on Windows vs Unix for typical C/C++ programs and typical FPC programs.
## Summary When writing #41328 I found found by reading the code that the current implementation of `SysExecute` on Windows results in different arguments being passed compared to the Unix version. ## System Information <!-- The more information are provided the easier it is to replicate the bug --> - **Operating system:** Windows - **Processor architecture:** x86-64 - **Compiler version:** trunk - **Device:** N/A ## Reason to believe the bug exists * On Windows, https://gitlab.com/freepascal.org/fpc/source/-/blob/main/packages/fcl-process/src/win/process.inc#L209-215 uses a `MaybeQuoteIfNotQuoted` logic to deal with `TProcess.Parameters`. * On Unix `TProcess.Parameters` just becomes argv. ## Steps to reproduce * Write a Windows VC++ program that performs "echo". `#include <stdio.h>` followed by `int main(int ac, char** av){ printf("%s\n", av[1]); return 0; }` will suffice. * Call it. * Write a Free Pascal program that performs "echo". ```pas program Echo; begin writeln (ParamStr(1)); end. ``` * Also call it. ## What is the current bug behavior? For a `TProcess.Parameters` containing one member, `'"a"'`, being used to call `echo` or a Windows VC++ program written to perform the same thing. * On Windows, `MaybeQuoteIfNotQuoted` would not try to quote the string because it appears to be quoted. As a result, the program would receive the CommandLine `echo.exe "a"` and print only `a`. * On Unix, the program would print `"a"`. ## What is the expected (correct) behavior? It should print `"a"` like on Linux. This translates to a CommandLine of `"\"a\""`. ## Possible fixes I believe the Unix implementation to be more logical and the Windows version should be changed to match. Instead of `MaybeQuoteIfNotQuoted`, what we need is a `QuoteIfNeeded` or even `Quote` (always): ```pas Function Quote(Const S : TProcessString) : TProcessString; var C : Char; Backslashes : Integer; begin Backslashes = 0; Result := '"'; for C in S do case C of '"': begin Result := Result + StringOfChar('\', Backslashes * 2 + 1) + C; Backslashes := 0; end '\': Backslashes := Backslashes + 1; else begin Result := Result + StringOfChar('\', Backslashes) + C; Backslashes := 0; end Result := Result + StringOfChar('\', Backslashes * 2) + '"'; end; Function QuoteIfNeeded`(Const S : TProcessString) : TProcessString begin If (Pos(' ',S)<>0) or (pos('"',S)<>0) or (pos(#9,S)<>0) then Result := Quote(S) else Result := S; end; ```
issue