Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 68 additions & 30 deletions src/flutter_pty_win.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,76 @@
#include "include/dart_api_dl.h"
#include "include/dart_native_api.h"

// Windows' CreateProcessW takes the whole command line as one string, so any
// token containing a space or tab must be quoted or it splits into several
// argv entries for the child (and, worse, can throw off CreateProcessW's own
// search for where the executable name ends when lpApplicationName is NULL -
// e.g. "C:\Program Files\Git\bin\bash.exe" without quotes). Windows filenames
// cannot contain a double quote, so a token that needs quoting here never
// contains one that would itself need escaping.
static int needs_quoting(const char *token)
{
if (token == NULL || token[0] == 0)
{
return 1;
}

for (int i = 0; token[i] != 0; i++)
{
if (token[i] == ' ' || token[i] == '\t')
{
return 1;
}
}

return 0;
}

static int quoted_length(char *token)
{
int length = (int)strlen(token);
return needs_quoting(token) ? length + 2 : length;
}

static void append_token(LPWSTR command, int *pos, char *token)
{
int quote = needs_quoting(token);

if (quote)
{
command[(*pos)++] = L'"';
}

for (int j = 0; token[j] != 0; j++)
{
command[(*pos)++] = (WCHAR)token[j];
}

if (quote)
{
command[(*pos)++] = L'"';
}
}

static LPWSTR build_command(char *executable, char **arguments)
{
int command_length = 0;

if (executable != NULL)
{
command_length += (int)strlen(executable);
command_length += quoted_length(executable);
}

if (arguments != NULL)
// arguments[0] duplicates executable - flutter_pty's Dart side always
// prepends it so Unix's execvp() gets a conventional argv[0], but here
// it would otherwise be written out a second time. Start at index 1.
if (arguments != NULL && arguments[0] != NULL)
{
int i = 0;
int i = 1;

while (arguments[i] != NULL)
{
command_length += (int)strlen(arguments[i]) + 1;
command_length += quoted_length(arguments[i]) + 1;
i++;
}
}
Expand All @@ -31,42 +85,26 @@ static LPWSTR build_command(char *executable, char **arguments)

if (command != NULL)
{
int i = 0;
int pos = 0;

if (executable != NULL)
{
int j = 0;

while (executable[j] != 0)
{
command[i] = (WCHAR)executable[j];
i++;
j++;
}
append_token(command, &pos, executable);
}

if (arguments != NULL)
if (arguments != NULL && arguments[0] != NULL)
{
int j = 0;
int i = 1;

while (arguments[j] != NULL)
while (arguments[i] != NULL)
{
command[i++] = ' ';

int k = 0;

while (arguments[j][k] != 0)
{
command[i] = (WCHAR)arguments[j][k];
i++;
k++;
}

j++;
command[pos++] = L' ';
append_token(command, &pos, arguments[i]);
i++;
}
}

command[i] = 0;
command[pos] = 0;
}

return command;
Expand Down Expand Up @@ -467,4 +505,4 @@ FFI_PLUGIN_EXPORT int pty_getpid(PtyHandle *handle)
FFI_PLUGIN_EXPORT char *pty_error()
{
return error_message;
}
}