rmyorston / busybox-w32

WIN32 native port of BusyBox.
https://frippery.org/busybox
Other
684 stars 125 forks source link

BusyBox shell does not work under GitKraken #229

Open vapaamies opened 3 years ago

vapaamies commented 3 years ago

When set as Git hooks interpreter in GitKraken, BusyBox shell ends with error:

52525e4fa93c143a233fe254417cd0b1cf64aa1f: line 1: syntax error: unterminated quoted string
Hook process exited.

This is post-checkout hook. The post-checkout is empty script:

#!/bin/sh

I have to use the shell from MinGit without BusyBox, it works as expected. But being executed inside the hook running by that shell, BusyBox works well too.

After a short research, I suspect bad $PATH variable handling. It contains the ( character because of C:/Program Files (x86)/NVIDIA Corporation/PhysX/Common added automatically by NVidia driver.

rmyorston commented 3 years ago

Using SysInternals Process Monitor I was able to determine that the hook handling shell was run with this command:

C:\Windows\system32\cmd.exe /d /s /c ""C:\Windows\System32\sh.exe" -lc 'C:\\\\Users\\\\rmy\\\\Documents\\\\gitrepo\\\\.git\\\\hooks\\\\post-checkout 28cb6036508444c3747a0fed2ce94438a0970992 28cb6036508444c3747a0fed2ce94438a0970992 1'"

That's a heck of a lot of backslashes and quite a lot of quotes.

The arguments the busybox-w32 shell saw were:

argv[0] c:/windows/system32/sh
argv[1] -lc
argv[2] 'C:\\\\\\\\Users\\\\\\\\rmy\\\\\\\\Documents\\\\\\\\gitrepo\\\\\\\\.git\\\\\\\\hooks\\\\\\\\post-checkout
argv[3] 28cb6036508444c3747a0fed2ce94438a0970992
argv[4] 28cb6036508444c3747a0fed2ce94438a0970992
argv[5] 1'

This has even more backslashes!

The argument to the -c option was intended to be everything in single quotes, but they clearly haven't had the desired effect. The shell is trying to run the command 'C:\\\\\\\\Users\\\\\\\\rmy\\\\\\\\Documents\\\\\\\\gitrepo\\\\\\\\.git\\\\\\\\hooks\\\\\\\\post-checkout which, as the error states, is an unterminated quoted string. The closing single quote doesn't appear until argv[5] which again is improperly terminated.

There should only be three arguments: the path to the shell, the options -lc and the string the shell is supposed to run (without any quotes).

It's possible GitKraken could avoid this problem by using double quotes instead of single quotes, but Windows command lines are a bit of a mystery.

There isn't much busybox-w32 can do about it. It gets its arguments from the mingw-w64 start-up code which calls the Microsoft __getmainargs or __wgetmainargs functions to split the command line string into separate arguments.

Apparently the MSYS2 shell from MinGit has its own, different arrangements.

vapaamies commented 3 years ago

Sent feedback to GitKraken Team.

ale5000-git commented 2 years ago

@rmyorston Is it possible to bypass Windows command line parsing entirely? Maybe just ignoring argv, using LPSTR GetCommandLineA(); to get raw command line and using custom code to parse it like a Linux shell would avoid all issues with '

rmyorston commented 2 years ago

Is it possible to bypass Windows command line parsing entirely?

Sure, it's possible. I don't think it's a good idea, though.

Because of reasons busybox-w32 already has two modes of command line handling. These are both necessary so parsing the command line like a Linux shell would require a third mode.

It's a can of worms I'd prefer not to open.

Incidentally, to expand a bit on what I mentioned above, the MSYS2 shell does appear to perform its own command line processing:

C:\Users\rmy>c:\msys64\usr\bin\sh -c 'echo hello'
hello

This is definitely not how a standard WIN32 application would process that command line:

C:\Users\rmy>cmd /c 'echo hello'
''echo' is not recognized as an internal or external command,
operable program or batch file.

C:\Users\rmy>c:\users\rmy\sh -c 'echo hello'
hello': line 0: syntax error: unterminated quoted string

cmd.exe and the busybox-w32 shell are both standard WIN32 applications and don't like the single quotes. Everyone likes double quotes, though:

C:\Users\rmy>c:\msys64\usr\bin\sh -c "echo hello"
hello

C:\Users\rmy>cmd /c "echo hello"
hello

C:\Users\rmy>c:\users\rmy\sh -c "echo hello"
hello

It appears that GitKraken is relying on the non-standard (from a Windows perspective) behaviour of the MSYS2 shell.

ale5000-git commented 2 years ago

Is it possible to bypass Windows command line parsing entirely?

Sure, it's possible. I don't think it's a good idea, though.

Because of reasons busybox-w32 already has two modes of command line handling. These are both necessary so parsing the command line like a Linux shell would require a third mode.

I'm not sure if it is possible, but isn't possible to reuse the command line parsing inside ash shell of busybox and with its result override argv and argc?

PS: The zip.exe also override it, since when using * in zip command line it ignore the shell expansion and use its own.

rmyorston commented 2 years ago

The zip.exe also override it

Related: issue #235