File 1034-erts-Fix-batch-file-invocation-in-open_port.patch of Package erlang
From 2b64e8b98c114123a5386e99d6eb28483a52834d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Tue, 2 Apr 2024 12:13:14 +0200
Subject: [PATCH] erts: Fix batch file invocation in open_port
Co-authored-by: Dan Gudmundsson <dgud@erlang.org>
---
erts/emulator/sys/win32/sys.c | 71 ++++++++++++++++++++++++++++-------
1 file changed, 58 insertions(+), 13 deletions(-)
diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c
index 2a37c075f8..841487edc7 100644
--- a/erts/emulator/sys/win32/sys.c
+++ b/erts/emulator/sys/win32/sys.c
@@ -1442,6 +1442,42 @@ int parse_command(wchar_t* cmd){
}
+static int requires_quote(wchar_t c, int applType) {
+ switch (c) {
+ case L' ':
+ return 1;
+ case L'&':
+ case L'<':
+ case L'>':
+ case L'[':
+ case L']':
+ case L'|':
+ case L'{':
+ case L'}':
+ case L'^':
+ case L'=':
+ case L';':
+ case L'!':
+ case L'\'':
+ case L'+':
+ case L',':
+ case L'`':
+ case L'~':
+ case L'\t':
+ case L'\r':
+ case L'\n':
+ /* According to [1], these characters need to be quoted when using
+ * `cmd /c`. Otherwise, using `&` (for example) can spawn other
+ * executables.
+ *
+ * [1]: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/cmd
+ */
+ return applType == APPL_DOS;
+ default:
+ return 0;
+ }
+}
+
/*
* Translating of command line arguments to correct format. In the examples
* below the '' are not part of the actual string.
@@ -1457,17 +1493,26 @@ int parse_command(wchar_t* cmd){
* one level of escaping since it takes a single long command line rather
* than the argument chunks that unix uses.
*/
-static int escape_and_quote(wchar_t *str, wchar_t *new, BOOL *quoted) {
+static int escape_and_quote(wchar_t *str,
+ int applType,
+ wchar_t *new,
+ BOOL *quoted) {
int i, j = 0;
- if (new == NULL)
+
+ if (new == NULL) {
*quoted = FALSE;
- else if (*quoted)
+ } else if (*quoted) {
new[j++] = L'"';
+ }
+
for ( i = 0; str[i] != L'\0'; i++,j++) {
- if (str[i] == L' ' && new == NULL && *quoted == FALSE) {
- *quoted = TRUE;
- j++;
- }
+ if (new == NULL &&
+ *quoted == FALSE &&
+ requires_quote(str[i], applType)) {
+ *quoted = TRUE;
+ j++;
+ }
+
/* check if we have to escape quotes */
if (str[i] == L'"') {
if (new) new[j] = L'\\';
@@ -1572,7 +1617,7 @@ create_child_process
return FALSE;
}
- quotedLen = escape_and_quote(execPath, NULL, &need_quote);
+ quotedLen = escape_and_quote(execPath, applType, NULL, &need_quote);
newcmdline = (wchar_t *)
erts_alloc(ERTS_ALC_T_TMP,
(11+quotedLen+wcslen(origcmd)-cmdlength)*sizeof(wchar_t));
@@ -1598,7 +1643,7 @@ create_child_process
createFlags = 0;
}
- ptr += escape_and_quote(execPath, ptr, &need_quote);
+ ptr += escape_and_quote(execPath, applType, ptr, &need_quote);
wcscpy(ptr, origcmd+cmdlength);
DEBUGF(("Creating child process: %S, createFlags = %d\n", newcmdline, createFlags));
@@ -1654,7 +1699,7 @@ create_child_process
if (argv == NULL) {
BOOL orig_need_q;
wchar_t *ptr;
- int ocl = escape_and_quote(execPath, NULL, &orig_need_q);
+ int ocl = escape_and_quote(execPath, applType, NULL, &orig_need_q);
if (run_cmd) {
newcmdline = (wchar_t *) erts_alloc(ERTS_ALC_T_TMP,
(ocl + 1 + 11)*sizeof(wchar_t));
@@ -1665,7 +1710,7 @@ create_child_process
(ocl + 1)*sizeof(wchar_t));
ptr = (wchar_t *) newcmdline;
}
- ptr += escape_and_quote(execPath, ptr, &orig_need_q);
+ ptr += escape_and_quote(execPath, applType, ptr, &orig_need_q);
ptr[0] = L'\0';
} else {
int sum = 0;
@@ -1686,7 +1731,7 @@ create_child_process
ar = argv;
while (*ar != NULL) {
- sum += escape_and_quote(*ar,NULL,qte+(ar - argv));
+ sum += escape_and_quote(*ar, applType, NULL,qte+(ar - argv));
sum++; /* space */
++ar;
}
@@ -1698,7 +1743,7 @@ create_child_process
n += 11;
}
while (*ar != NULL) {
- n += escape_and_quote(*ar,n,qte+(ar - argv));
+ n += escape_and_quote(*ar, applType, n,qte+(ar - argv));
*n++ = L' ';
++ar;
}
--
2.35.3