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

openSUSE Build Service is sponsored by