Hi Marco, > $ python3.12 > Python 3.12.8 (main, Jan 31 2025, 21:29:51) [GCC 12.4.0] on cygwin > Type "help", "copyright", "credits" or "license" for more information. > import subprocess > subprocess.run(['./test.exe', '"', " a b c"]) > argv[0] = ./test > argv[1] = " > argv[2] = a b c > CompletedProcess(args=['./test.exe', '"', ' a b c'], returncode=0) > > it seems correct to me for a Cygwin Python
This behavior appears correct for Cygwin Python because it assumes it is running on a POSIX system. As a result, it uses Cygwin's simulated `execve` system call rather than Windows' command-line parsing mechanism and the parsing mechanism within Cygwin itself is consistent so everything goes fine here. To be more specific, the issue happens when a program thinks it is still on Windows, so it uses Microsoft C startup convention to escape and pass command line string and spawn that executable with CreateProcess API. But it turns out Cygwin C startup function doesn't fully follow that convention. > PS: Windows is not very consistent on quoting behaviour, e.g. > https://github.com/Azure/azure-cli/blob/dev/doc/quoting-issues-with-powershell.md I think we should distinguish between shell parsing and command-line parsing -- command-line parsing is all done by the executable itself instead of the shell (powershell, cmd, bash etc.) On Windows, arguments are parsed by the executable itself rather than the shell. This means the shell does not pass an argv[] array directly to the executable but instead sends the full command line string. Here is a good article about this https://daviddeley.com/autohotkey/parameters/parameters.htm#WIN Regards, splitline On Tue, Feb 4, 2025 at 2:15 PM Splitline Huang <splitl...@devco.re> wrote: > > Hello Cygwin team, > > I am splitline from DEVCORE research team. I recently have observed an > inconsistency > in how Cygwin handles command-line parsing compared to Microsoft’s > implementation. > > > According to Microsoft’s documentation [1], the \" sequence should always be > interpreted as a literal double quote ("): > > A double quote mark preceded by a backslash (\") is interpreted as a literal > > double quote mark ("). > > However, in Cygwin, the same sequence treats the backslash as a literal > character > and starts quote mode instead. > > [1] > https://learn.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments > > This inconsistency can cause unexpected behavior when passing executable > arguments > via the command line (as opposed to Cygwin’s `execve` method), potentially > leading > to argument injection vulnerabilities. > > > Below is my testing process using the Python from Python.org (not the Cygwin > version): > > > splitline@SPLITLINE0D06 ~ > > $ which gcc > > /usr/bin/gcc > > splitline@SPLITLINE0D06 ~ > > $ cat test.c > > #include <stdio.h> > > > int main(int argc, char* argv[], char* envp[]) { > > for (int i = 0; i < argc; ++i) > > printf("argv[%d] = %s\n", i, argv[i]); > > } > > splitline@SPLITLINE0D06 ~ > > $ gcc test.c -o test.exe > > splitline@SPLITLINE0D06 ~ > > $ which python > > /cygdrive/c/Python313/python > > splitline@SPLITLINE0D06 ~ > > $ python > > Python 3.13.1 (tags/v3.13.1:0671451, Dec 3 2024, 19:06:28) [MSC v.1942 > > 64 bit (AMD64)] on win32 > > Type "help", "copyright", "credits" or "license" for more information. > > >>> import subprocess > > >>> subprocess.run(['./test.exe', '"', " a b c"]) # should be only 2 args > > argv[0] = ./test > > argv[1] = \ > > argv[2] = a > > argv[3] = b > > argv[4] = c > > CompletedProcess(args=['./test.exe', '"', ' a b c'], returncode=0) > > >>> > > > > As we can see, it should originally be only 2 arguments: ["] and [ a b c]. > However, > the command line is parsed into 4 different arguments. > > Note: With that Python code, the spawned command line is: ./test.exe \" " a b > c" > > Please let me know if you have any questions, thanks! > > Best regards, > splitline > DEVCORE > -- Problem reports: https://cygwin.com/problems.html FAQ: https://cygwin.com/faq/ Documentation: https://cygwin.com/docs.html Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple