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

Reply via email to