aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <adamdharrison@gmail.com>2022-09-29 23:37:20 -0400
committerAdam <adamdharrison@gmail.com>2022-10-06 21:09:53 -0400
commit3942f2fe1deac8c1016c69fdc6b66dc9ea0fe589 (patch)
tree6795b04cc700e80ac24fe013c5a2ca485b94bd88
parente34a3ca78f0f39ec2cc93e17ebfa36d7e630bfdc (diff)
downloadlite-xl-fix-win32-process-arguments.tar.gz
lite-xl-fix-win32-process-arguments.zip
Fixed process layer argument quoting; allows for strings with spaces. And added ability to specify a literal, in the style of python.fix-win32-process-arguments
-rw-r--r--src/api/process.c68
1 files changed, 46 insertions, 22 deletions
diff --git a/src/api/process.c b/src/api/process.c
index 82842176..eae2bf0d 100644
--- a/src/api/process.c
+++ b/src/api/process.c
@@ -125,22 +125,26 @@ static int process_start(lua_State* L) {
int retval = 1;
size_t env_len = 0, key_len, val_len;
const char *cmd[256] = { NULL }, *env_names[256] = { NULL }, *env_values[256] = { NULL }, *cwd = NULL;
- bool detach = false;
+ bool detach = false, literal = false;
int deadline = 10, new_fds[3] = { STDIN_FD, STDOUT_FD, STDERR_FD };
- luaL_checktype(L, 1, LUA_TTABLE);
- #if LUA_VERSION_NUM > 501
- lua_len(L, 1);
- #else
- lua_pushinteger(L, (int)lua_objlen(L, 1));
- #endif
- size_t cmd_len = luaL_checknumber(L, -1); lua_pop(L, 1);
- size_t arg_len = lua_gettop(L);
- for (size_t i = 1; i <= cmd_len; ++i) {
- lua_pushinteger(L, i);
- lua_rawget(L, 1);
- cmd[i-1] = luaL_checkstring(L, -1);
+ size_t arg_len = lua_gettop(L), cmd_len;
+ if (lua_type(L, 1) == LUA_TTABLE) {
+ #if LUA_VERSION_NUM > 501
+ lua_len(L, 1);
+ #else
+ lua_pushinteger(L, (int)lua_objlen(L, 1));
+ #endif
+ cmd_len = luaL_checknumber(L, -1); lua_pop(L, 1);
+ for (size_t i = 1; i <= cmd_len; ++i) {
+ lua_pushinteger(L, i);
+ lua_rawget(L, 1);
+ cmd[i-1] = luaL_checkstring(L, -1);
+ }
+ } else {
+ literal = true;
+ cmd[0] = luaL_checkstring(L, 1);
+ cmd_len = 1;
}
-
// this should never trip
// but if it does we are in deep trouble
assert(cmd[0]);
@@ -239,15 +243,35 @@ static int process_start(lua_State* L) {
siStartInfo.hStdOutput = self->child_pipes[STDOUT_FD][1];
siStartInfo.hStdError = self->child_pipes[STDERR_FD][1];
char commandLine[32767] = { 0 }, environmentBlock[32767], wideEnvironmentBlock[32767*2];
- strcpy(commandLine, cmd[0]);
int offset = 0;
- for (size_t i = 1; i < cmd_len; ++i) {
- size_t len = strlen(cmd[i]);
- offset += len + 1;
- if (offset >= sizeof(commandLine))
- break;
- strcat(commandLine, " ");
- strcat(commandLine, cmd[i]);
+ if (!literal) {
+ for (size_t i = 0; i < cmd_len; ++i) {
+ size_t len = strlen(cmd[i]);
+ if (offset + len + 2 >= sizeof(commandLine)) break;
+ if (i > 0)
+ commandLine[offset++] = ' ';
+ commandLine[offset++] = '"';
+ int backslashCount = 0; // Yes, this is necessary.
+ for (size_t j = 0; j < len && offset + 2 + backslashCount < sizeof(commandLine); ++j) {
+ if (cmd[i][j] == '\\')
+ ++backslashCount;
+ else if (cmd[i][j] == '"') {
+ for (size_t k = 0; k < backslashCount; ++k)
+ commandLine[offset++] = '\\';
+ commandLine[offset++] = '\\';
+ backslashCount = 0;
+ } else
+ backslashCount = 0;
+ commandLine[offset++] = cmd[i][j];
+ }
+ if (offset + 1 + backslashCount >= sizeof(commandLine)) break;
+ for (size_t k = 0; k < backslashCount; ++k)
+ commandLine[offset++] = '\\';
+ commandLine[offset++] = '"';
+ }
+ commandLine[offset] = 0;
+ } else {
+ strncpy(commandLine, cmd[0], sizeof(commandLine));
}
offset = 0;
for (size_t i = 0; i < env_len; ++i) {