Path: csiph.com!usenet.pasdenom.info!gegeweb.org!eternal-september.org!feeder.eternal-september.org!mx05.eternal-september.org!.POSTED!not-for-mail From: Steven Simpson Newsgroups: comp.lang.java.programmer Subject: Re: exec problem is JDK 1.7.0_21 Date: Wed, 24 Apr 2013 10:26:04 +0100 Organization: A noiseless patient Spider Lines: 225 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit Injection-Info: mx05.eternal-september.org; posting-host="d8629fa69e7130fbf7ceb3509cbe6bc2"; logging-data="5913"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/xwdXxWLnyR7Hmxaf5gQpomSdixWuf57k=" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130329 Thunderbird/17.0.5 In-Reply-To: Cancel-Lock: sha1:gTgA7LhOo5wOjMZgZ1pChc1HATg= Xref: csiph.com comp.lang.java.programmer:23618 On 24/04/13 07:29, Sven Köhler wrote: > Am 24.04.2013 01:39, schrieb Steven Simpson: >>> Also, you have to add another backslash if the quote does not terminate >>> the argument. >> Again, I took it to mean that the first two rules produce the same >> result, so \\\" and \\" both produce \". > The documentation of CommandLineToArgv is incomplete. Agreed. >> Where are you getting the notion that the first two rules imply >> different quotes? I interpret both as being literal (inner, right?). > Well, by testing. As you can test yourself on the command line, \\" will > result in a closing quote and \" and \\\" will result in non-closing quotes. That's not what I'm seeing. In fact, backslashes appear to have no effect! Cross-compiled with mingw32: #include #include #include #include static void test(const wchar_t *s) { printf("\nInput line: %ls\n", s); int argc; LPWSTR *argv = CommandLineToArgvW(s, &argc); if (!argv) { printf(" unable to parse\n"); } else { printf(" arg count: %d\n", argc); for (int i = 0; i < argc; i++) printf(" [%d]=[%ls]\n", i, argv[i]); LocalFree(argv); } } int main(void) { test(L"foo"); test(L"foo\""); test(L"foo\\\""); test(L"foo\\\\\""); test(L"foo\\\\\\\""); test(L"\"foo"); test(L"\"foo\""); test(L"\"foo\\\""); test(L"\"foo\\\\\""); test(L"\"foo\\\\\\\""); test(L"foo bar"); test(L"foo\"bar"); test(L"foo\\\"bar"); test(L"foo\\\\\"bar"); test(L"foo\\\\\\\"bar"); test(L"foo\\ bar"); test(L"foo\\\\ bar"); test(L"foo\\\\\\ bar"); test(L"\"foo bar\""); test(L"\"foo \\\"bar\""); test(L"\"foo \\\\\"bar\""); test(L"\"foo \\\\\\\"bar\""); return 0; } Output: Input line: foo arg count: 1 [0]=[foo] Input line: foo" arg count: 1 [0]=[foo"] Okay, so if the quote doesn't start the argument, it's literal. Input line: foo\" arg count: 1 [0]=[foo\"] Input line: foo\\" arg count: 1 [0]=[foo\\"] Input line: foo\\\" arg count: 1 [0]=[foo\\\"] These backslashes aren't folded in any way. Input line: "foo arg count: 1 [0]=[foo] Input line: "foo" arg count: 1 [0]=[foo] So the leading quote is stripped, and the closing quote is optional - no error. Input line: "foo\" arg count: 1 [0]=[foo\] Input line: "foo\\" arg count: 1 [0]=[foo\\] Input line: "foo\\\" arg count: 1 [0]=[foo\\\] Inside the quoted argument, backslashes still have no special meaning. And I can't get a literal quote character. Input line: foo bar arg count: 2 [0]=[foo] [1]=[bar] So a space splits arguments. Input line: foo"bar arg count: 1 [0]=[foo"bar] The quote inside an unquoted argument is taken as literal. Input line: foo\"bar arg count: 1 [0]=[foo\"bar] Input line: foo\\"bar arg count: 1 [0]=[foo\\"bar] Input line: foo\\\"bar arg count: 1 [0]=[foo\\\"bar] The backslashes are literal in the middle of the unquoted argument. Input line: foo\ bar arg count: 2 [0]=[foo\] [1]=[bar] Input line: foo\\ bar arg count: 2 [0]=[foo\\] [1]=[bar] Input line: foo\\\ bar arg count: 2 [0]=[foo\\\] [1]=[bar] Just checking that there's no unspecified way to escape a space. Input line: "foo bar" arg count: 1 [0]=[foo bar] The quotes cause the space to be taken literally. Input line: "foo \"bar" arg count: 2 [0]=[foo \] [1]=[bar] Input line: "foo \\"bar" arg count: 2 [0]=[foo \\] [1]=[bar] Input line: "foo \\\"bar" arg count: 2 [0]=[foo \\\] [1]=[bar] Backslashes are still literal, and the next quote closes the argument regardless. Plus, the extra quote after [bar] is not literal. There seems to be no way to escape a space other than enclosing the entire argument in quotes. Once inside the quotes, there's no way to escape anything else (like a literal quote), so there's no way to escape an argument containing a space and a quote. Backslashes behave literally everywhere. Is the program using CommandLineToArgvW incorrectly? Are there any other input strings to try? > Also, there HAS to be a way to distinguish a closing vs. a non-closing > quote. Otherwise you wouldn't know whether the quotes in \" \\" and \\\" > were closing or not. That's it is not documented is just a real shame! What I'm seeing now is that general escaping is impossible, not merely documented badly. :-( -- ss at comp dot lancs dot ac dot uk