From 10d1c6da187e2c7b8d50535a7701c0b944ded8c8 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Tue, 3 Jan 2023 03:22:09 -0800 Subject: [PATCH] Support `argv[0]` munging on Windows --- libc/calls/mkntcmdline.c | 17 +++++++---------- libc/calls/ntspawn.c | 2 +- libc/calls/ntspawn.h | 2 +- test/libc/calls/mkntcmdline_test.c | 24 ++++++++++++------------ tool/emacs/cosmo-platform-constants.el | 1 - 5 files changed, 21 insertions(+), 25 deletions(-) diff --git a/libc/calls/mkntcmdline.c b/libc/calls/mkntcmdline.c index 6d2cf4367..fb8b72ba6 100644 --- a/libc/calls/mkntcmdline.c +++ b/libc/calls/mkntcmdline.c @@ -61,15 +61,12 @@ static inline int IsAlpha(int c) { // TODO(jart): this needs fuzzing and security review // // @param cmdline is output buffer -// @param prog is frontloaded as argv[0] // @param argv is an a NULL-terminated array of UTF-8 strings // @return 0 on success, or -1 w/ errno // @raise E2BIG if everything is too huge // @see "Everyone quotes command line arguments the wrong way" MSDN // @see libc/runtime/getdosargv.c -textwindows int mkntcmdline(char16_t cmdline[ARG_MAX / 2], const char *prog, - char *const argv[]) { - char *arg; +textwindows int mkntcmdline(char16_t cmdline[ARG_MAX / 2], char *const argv[]) { uint64_t w; wint_t x, y; int slashes, n; @@ -81,16 +78,16 @@ textwindows int mkntcmdline(char16_t cmdline[ARG_MAX / 2], const char *prog, bzero(ansiargv, sizeof(ansiargv)); argv = ansiargv; } - for (arg = prog, k = i = 0; arg; arg = argv[++i]) { + for (k = i = 0; argv[i]; ++i) { if (i) APPEND(u' '); - if ((needsquote = NeedsQuotes(arg))) APPEND(u'"'); + if ((needsquote = NeedsQuotes(argv[i]))) APPEND(u'"'); for (slashes = j = 0;;) { - x = arg[j++] & 255; + x = argv[i][j++] & 255; if (x >= 0300) { n = ThomPikeLen(x); x = ThomPikeByte(x); while (--n) { - if ((y = arg[j++] & 255)) { + if ((y = argv[i][j++] & 255)) { x = ThomPikeMerge(x, y); } else { x = 0; @@ -101,9 +98,9 @@ textwindows int mkntcmdline(char16_t cmdline[ARG_MAX / 2], const char *prog, if (!x) break; if (x == '/' || x == '\\') { if (!i) { - // turn / into \ for first arg + // turn / into \ for first argv[i] x = '\\'; - // turn \c\... into c:\ for first arg + // turn \c\... into c:\ for first argv[i] if (k == 2 && IsAlpha(cmdline[1]) && cmdline[0] == '\\') { cmdline[0] = cmdline[1]; cmdline[1] = ':'; diff --git a/libc/calls/ntspawn.c b/libc/calls/ntspawn.c index 4a68de786..5632d33ec 100644 --- a/libc/calls/ntspawn.c +++ b/libc/calls/ntspawn.c @@ -84,7 +84,7 @@ textwindows int ntspawn( sizeof(*block), 0)) && (block = MapViewOfFileEx(handle, kNtFileMapRead | kNtFileMapWrite, 0, 0, sizeof(*block), 0)) && - mkntcmdline(block->cmdline, prog, argv) != -1 && + mkntcmdline(block->cmdline, argv) != -1 && mkntenvblock(block->envvars, envp, extravar, block->buf) != -1 && CreateProcess(prog16, block->cmdline, opt_lpProcessAttributes, opt_lpThreadAttributes, bInheritHandles, diff --git a/libc/calls/ntspawn.h b/libc/calls/ntspawn.h index 57ef5b02c..05b0fd193 100644 --- a/libc/calls/ntspawn.h +++ b/libc/calls/ntspawn.h @@ -6,7 +6,7 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) COSMOPOLITAN_C_START_ -int mkntcmdline(char16_t[ARG_MAX / 2], const char *, char *const[]) _Hide; +int mkntcmdline(char16_t[ARG_MAX / 2], char *const[]) _Hide; int mkntenvblock(char16_t[ARG_MAX / 2], char *const[], const char *, char[ARG_MAX]) _Hide; int ntspawn(const char *, char *const[], char *const[], const char *, diff --git a/test/libc/calls/mkntcmdline_test.c b/test/libc/calls/mkntcmdline_test.c index 1102c66cc..456b48548 100644 --- a/test/libc/calls/mkntcmdline_test.c +++ b/test/libc/calls/mkntcmdline_test.c @@ -26,38 +26,38 @@ char16_t cmdline[ARG_MAX / 2]; TEST(mkntcmdline, emptyArgvList_cantBeEmptyOnWindows) { - char *argv[] = {NULL}; - EXPECT_NE(-1, mkntcmdline(cmdline, "foo", argv)); + char *argv[] = {"foo", NULL}; + EXPECT_NE(-1, mkntcmdline(cmdline, argv)); EXPECT_STREQ(u"foo", cmdline); } TEST(mkntcmdline, emptyArgvListWithProg_isEmpty) { char *argv[] = {NULL}; - EXPECT_NE(-1, mkntcmdline(cmdline, argv[0], argv)); + EXPECT_NE(-1, mkntcmdline(cmdline, argv)); EXPECT_STREQ(u"", cmdline); } TEST(mkntcmdline, emptyArg_getsQuoted) { char *argv[] = {"", NULL}; - EXPECT_NE(-1, mkntcmdline(cmdline, argv[0], argv)); + EXPECT_NE(-1, mkntcmdline(cmdline, argv)); EXPECT_STREQ(u"\"\"", cmdline); } TEST(mkntcmdline, ignoranceIsBliss) { char *argv[] = {"echo", "hello", "world", NULL}; - EXPECT_NE(-1, mkntcmdline(cmdline, argv[0], argv)); + EXPECT_NE(-1, mkntcmdline(cmdline, argv)); EXPECT_STREQ(u"echo hello world", cmdline); } TEST(mkntcmdline, spaceInArgument_getQuotesWrappedAround) { char *argv[] = {"echo", "hello there", "world", NULL}; - EXPECT_NE(-1, mkntcmdline(cmdline, argv[0], argv)); + EXPECT_NE(-1, mkntcmdline(cmdline, argv)); EXPECT_STREQ(u"echo \"hello there\" world", cmdline); } TEST(mkntcmdline, justSlash) { char *argv[] = {"\\", NULL}; - EXPECT_NE(-1, mkntcmdline(cmdline, argv[0], argv)); + EXPECT_NE(-1, mkntcmdline(cmdline, argv)); EXPECT_STREQ(u"\\", cmdline); } @@ -67,7 +67,7 @@ TEST(mkntcmdline, testUnicode) { gc(strdup("要依法治国是赞美那些谁是公义的和惩罚恶人。 - 韩非")), NULL, }; - EXPECT_NE(-1, mkntcmdline(cmdline, argv1[0], argv1)); + EXPECT_NE(-1, mkntcmdline(cmdline, argv1)); EXPECT_STREQ(u"(╯°□°)╯ \"要依法治国是赞美那些谁是公义的和惩罚恶人。 - 韩非\"", cmdline); } @@ -79,7 +79,7 @@ TEST(mkntcmdline, fixAsBestAsWeCanForNow1) { "more <\"/C/Users/jart/AppData/Local/Temp/tmplquaa_d6\"", NULL, }; - EXPECT_NE(-1, mkntcmdline(cmdline, argv1[0], argv1)); + EXPECT_NE(-1, mkntcmdline(cmdline, argv1)); EXPECT_STREQ(u"C:\\WINDOWS\\system32\\cmd.exe /C \"more <" u"\"\"\"C:/Users/jart/AppData/Local/Temp/tmplquaa_d6\"\"\"\"", cmdline); @@ -92,14 +92,14 @@ TEST(mkntcmdline, fixAsBestAsWeCanForNow2) { "less /C/Users/jart/AppData/Local/Temp/tmplquaa_d6", NULL, }; - EXPECT_NE(-1, mkntcmdline(cmdline, argv1[0], argv1)); + EXPECT_NE(-1, mkntcmdline(cmdline, argv1)); EXPECT_STREQ(u"C:\\WINDOWS\\system32\\cmd.exe /C \"less " u"C:/Users/jart/AppData/Local/Temp/tmplquaa_d6\"", cmdline); } TEST(mkntcmdline, testWut) { - char *argv[] = {"redbean.com", "--strace", NULL}; - EXPECT_NE(-1, mkntcmdline(cmdline, "C:\\Users\\jart\\𝑟𝑒𝑑𝑏𝑒𝑎𝑛.com", argv)); + char *argv[] = {"C:\\Users\\jart\\𝑟𝑒𝑑𝑏𝑒𝑎𝑛.com", "--strace", NULL}; + EXPECT_NE(-1, mkntcmdline(cmdline, argv)); EXPECT_STREQ(u"C:\\Users\\jart\\𝑟𝑒𝑑𝑏𝑒𝑎𝑛.com --strace", cmdline); } diff --git a/tool/emacs/cosmo-platform-constants.el b/tool/emacs/cosmo-platform-constants.el index 1698ed28e..04b3fef01 100644 --- a/tool/emacs/cosmo-platform-constants.el +++ b/tool/emacs/cosmo-platform-constants.el @@ -30,7 +30,6 @@ "__SSP__" "__SSP_ALL__" "__unix__" - "__mips__" "__vax__" "__ns16000__" "__pic__"