Command argument parsing bugs vs regular win32 tools
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 240
- Forks
- 60
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 1
Description
The MSYS2 runtime does some amount of interpretation of its own of the incoming command line string (which mostly is a feature, I guess). However the MSYS2 (or cygwin I presume) specific argument parsing breaks a number of details regarding how generic win32 processes parse their command line string.
The LLVM testsuite runs a large number of test cases, that involve invoking executables such as sed and grep, where the arguments may involve tricky strings with regexes and similar, where the exact escaping/unescaping of tricky characters is cruicial. The LLVM testsuite doesn't know if the sed or grep (or other shell utils) invoked are regular win32 executables (e.g. built with mingw, e.g. provided by the GnuWin tool suite) or MSYS2 based ones (in particular, LLVM's testsuite can automatically locate the set of tools installed as part of Git for Windows, as they generally fit the bill perfectly and often can be found installed on users' systems).
The LLVM tests have run into a number of cases where the regular win32 argument quoting/escaping rules don't work with MSYS based tools; some of the issues can be avoided by choosing a different quoting/escaping strategy, but overall there doesn't seem to be a single strategy that works consistently with both MSYS2 based tools and regular win32 based tools.
-
If one wants to pass the argument
a"bto a regular win32 process, it is escaped asa\"b, which after argument parsing/unescaping gets parsed back intoa"b. If a MSYS2 based process is passeda\"b, it receivesa\binstead. This particular bug can be avoided by quoting the whole string instead; both win32 and MSYS2 based tools parse"a\"b"asa"b. -
If one wants to pass the argument
a[b\cto a regular win32 process, it doesn't need any extra escaping. If a MSYS2 based process is passed the argumenta[b\c, the executable receives the argumenta[bc. In this case, quoting the whole argument string, into"a[b\c"makes both win32 and MSYS2 based tools receive the same, expected argument. -
If one wants to pass the argument
a\b\\c\\\\dto a regular win32 process, it doesn't need any extra escaping either, and both win32 and MSYS2 based tools receive the same, the expected argument. However, if one quotes the whole argument (as a workaround to 1. or 2. above), the MSYS2 based tool receivesa\b\c\\dinstead, which wasn't what was intended. -
As a separate workaround to 2. and 3. above, one can choose to instead set the env variable
MSYS=noglob. That works around both issues 2. and 3., but breaks issue 1. above again, making botha\"band"a\"b"be parsed asa\binstead ofa\"b.
Or more consistently, here are the sets of inputs and parsed outputs:
| # | Input | MSYS2 default | MSYS=noglob | win32 |
|---|---|---|---|---|
| 1 | a[b\c |
a[bc |
a[b\c |
a[b\c |
| 2 | a\b\\c\\\\d |
a\b\\c\\\\d |
a\b\\c\\\\d |
a\b\\c\\\\d |
| 3 | a\"b |
a\b |
a\b |
a"b |
| 4 | "a[b\c" |
a[b\c |
a[b\c |
a[b\c |
| 5 | "a\b\\c\\\\d" |
a\b\c\\d |
a\b\\c\\\\d |
a\b\\c\\\\d |
| 6 | "a\"b" |
a"b |
a\b |
a"b |
So there doesn't seem to be any combination of quoting or setting MSYS=noglob that consistently reproduces what's expected (what the win32 equivalent app receives). By quoting case 1 and 3 into 4 and 6, but not quoting case 2, one can get something that works, but that's extremely brittle, as if case 2 requires quoting the argument for other reasons, it breaks again.
To reproduce, build a small test app like this with both the MSYS2 runtime and mingw, and try invoking it (e.g. from cmd.exe) with the various test input arguments:
#include <stdio.h>
int main(int argc, char **argv) {
for (int i = 0; i < argc; i++)
printf("%d: %s\n", i, argv[i]);
return 0;
}
I presume this is mostly an upstream cygwin issue and there's not much you want to try to do about it at the MSYS2 level, but I thought I'd file it here first, for visibility and input, before proceeding further upstream.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the provided small C argv-printing test app; build it once with the MSYS2 runtime and once with mingw, then invoke both from cmd.exe using the listed inputs. Compare outputs under default settings and MSYS=noglob against the win32 expectations. Done means the parsing discrepancy is reproduced and its fix or upstream disposition is established.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- operating-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100