File 0577-erts-Fix-so-that-quotes-are-respected-in-erlexec-arg.patch of Package erlang

From e19abfa3c45168f98ca6a9a2db438ee91e84597c Mon Sep 17 00:00:00 2001
From: Lukas Larsson <lukas@erlang.org>
Date: Tue, 22 Oct 2019 10:17:09 +0200
Subject: [PATCH 1/3] erts: Fix so that quotes are respected in erlexec args
 files

Before this fix any double space ('a  b') would be stripped to
a single space even if quoted.
---
 erts/etc/common/erlexec.c   | 128 ++++++++++++++++++++------------------------
 erts/test/erlexec_SUITE.erl |  39 +++++++++-----
 2 files changed, 82 insertions(+), 85 deletions(-)

diff --git a/erts/etc/common/erlexec.c b/erts/etc/common/erlexec.c
index 0f65341a89..85bb9bd455 100644
--- a/erts/etc/common/erlexec.c
+++ b/erts/etc/common/erlexec.c
@@ -199,7 +199,7 @@ void error(char* format, ...);
 
 static void usage_notsup(const char *switchname, const char *alt);
 static char **build_args_from_env(char *env_var);
-static char **build_args_from_string(char *env_var);
+static char **build_args_from_string(char *env_var, int allow_comments);
 static void initial_argv_massage(int *argc, char ***argv);
 static void get_parameters(int argc, char** argv);
 static void add_arg(char *new_arg);
@@ -1659,12 +1659,12 @@ static void add_epmd_port(void)
 static char **build_args_from_env(char *env_var)
 {
     char *value = get_env(env_var);
-    char **res = build_args_from_string(value);
+    char **res = build_args_from_string(value, 0);
     free_env_val(value);
     return res;
 }
 
-static char **build_args_from_string(char *string)
+static char **build_args_from_string(char *string, int allow_comments)
 {
     int argc = 0;
     char **argv = NULL;
@@ -1673,7 +1673,7 @@ static char **build_args_from_string(char *string)
     int s_alloced = 0;
     int s_pos = 0;
     char *p = string;
-    enum {Start, Build, Build0, BuildSQuoted, BuildDQuoted, AcceptNext} state;
+    enum {Start, Build, Build0, BuildSQuoted, BuildDQuoted, AcceptNext, BuildComment} state;
 
 #define ENSURE()					\
     if (s_pos >= s_alloced) {			        \
@@ -1705,6 +1705,11 @@ static char **build_args_from_string(char *string)
 	    break;
 	case Build0:
 	    switch (*p) {
+            case '\n':
+	    case '\f':
+	    case '\r':
+	    case '\t':
+	    case '\v':
 	    case ' ':
 		++p;
 		break;
@@ -1718,6 +1723,11 @@ static char **build_args_from_string(char *string)
 	    break;
 	case Build:
 	    switch (*p) {
+	    case '\n':
+	    case '\f':
+	    case '\r':
+	    case '\t':
+	    case '\v':
 	    case ' ':
 	    case '\0':
 		ENSURE();
@@ -1737,6 +1747,13 @@ static char **build_args_from_string(char *string)
 		++p;
 		state = AcceptNext;
 		break;
+            case '#':
+                if (allow_comments) {
+                    ++p;
+                    state = BuildComment;
+                    break;
+                }
+                /* fall-through */
 	    default:
 		ENSURE();
 		(*cur_s)[s_pos++] = *p++;
@@ -1772,14 +1789,19 @@ static char **build_args_from_string(char *string)
 	    }
 	    break;
 	case AcceptNext:
-	    if (!*p) {
-		state = Build;
-	    } else {
+	    if (*p) {
 		ENSURE();
 		(*cur_s)[s_pos++] = *p++;
 	    }
 	    state = Build;
 	    break;
+        case BuildComment:
+            if (*p == '\n' || *p == '\0') {
+                state = Build;
+            } else {
+                p++;
+            }
+            break;
 	}
     }
 done:
@@ -1804,30 +1826,16 @@ errno_string(void)
     return str;
 }
 
+#define FILE_BUFF_SIZE 1024
+
 static char **
 read_args_file(char *filename)
 {
-    int c, aix = 0, quote = 0, cmnt = 0, asize = 0;
-    char **res, *astr = NULL;
     FILE *file;
-
-#undef EAF_CMNT
-#undef EAF_QUOTE
-#undef SAVE_CHAR
-
-#define EAF_CMNT	(1 << 8)
-#define EAF_QUOTE	(1 << 9)
-#define SAVE_CHAR(C)						\
-    do {							\
-	if (!astr)						\
-	    astr = emalloc(sizeof(char)*(asize = 20));		\
-	if (aix == asize)					\
-	    astr = erealloc(astr, sizeof(char)*(asize += 20));	\
-	if (' ' != (char) (C))					\
-	    astr[aix++] = (char) (C);				\
-	else if (aix > 0 && astr[aix-1] != ' ')			\
-	    astr[aix++] = ' ';					\
-   } while (0)
+    char buff[FILE_BUFF_SIZE+1];
+    size_t astr_sz = 0, sz;
+    char *astr = buff;
+    char **res;
 
     do {
 	errno = 0;
@@ -1839,63 +1847,41 @@ read_args_file(char *filename)
 		     errno_string());
     }
 
-    while (1) {
-	c = getc(file);
-	if (c == EOF) {
-	    if (ferror(file)) {
-		if (errno == EINTR) {
-		    clearerr(file);
-		    continue;
-		}
-		usage_format("Failed to read arguments file \"%s\": %s\n",
-			     filename,
-			     errno_string());
-	    }
-	    break;
-	}
+    sz = fread(astr, 1, FILE_BUFF_SIZE, file);
 
-	switch (quote | cmnt | c) {
-	case '\\':
-	    quote = EAF_QUOTE;
-	    break;
-	case '#':
-	    cmnt = EAF_CMNT;
-	    break;
-	case EAF_CMNT|'\n':
-	    cmnt = 0;
-	    /* Fall through... */
-	case '\n':
-	case '\f':
-	case '\r':
-	case '\t':
-	case '\v':
-	    if (!quote)
-		c = ' ';
-	    /* Fall through... */
-	default:
-	    if (!cmnt)
-		SAVE_CHAR(c);
-	    quote = 0;
-	    break;
-	}
+    while (!feof(file) && sz == FILE_BUFF_SIZE) {
+        if (astr == buff) {
+            astr = emalloc(FILE_BUFF_SIZE*2+1);
+            astr_sz = FILE_BUFF_SIZE;
+            memcpy(astr, buff, sizeof(buff));
+        } else {
+            astr_sz += FILE_BUFF_SIZE;
+            astr = erealloc(astr,astr_sz+FILE_BUFF_SIZE+1);
+        }
+        sz = fread(astr+astr_sz, 1, FILE_BUFF_SIZE, file);
+    }
+
+    if (ferror(file)) {
+        usage_format("Failed to read arguments file \"%s\": %s\n",
+                     filename,
+                     errno_string());
     }
 
-    SAVE_CHAR('\0');
+    astr[astr_sz + sz] = '\0';
 
     fclose(file);
 
     if (astr[0] == '\0')
 	res = NULL;
     else
-	res = build_args_from_string(astr);
+	res = build_args_from_string(astr, !0);
 
-    efree(astr);
+    if (astr != buff)
+        efree(astr);
 
     return res;
 
-#undef EAF_CMNT
-#undef EAF_QUOTE
-#undef SAVE_CHAR
+#undef FILE_BUFF_SIZE
 }
 
 
diff --git a/erts/test/erlexec_SUITE.erl b/erts/test/erlexec_SUITE.erl
index 952e6da4dc..fe8c6426e0 100644
--- a/erts/test/erlexec_SUITE.erl
+++ b/erts/test/erlexec_SUITE.erl
@@ -129,21 +129,26 @@ args_file(Config) when is_list(Config) ->
 		     " -args_file ~s#acomment~n"
 		     "~n"
 		     "-MiscArg7~n"
+		     "-MiscArg8 'val  with  double   space'~n"
+		     "-MiscArg9 '~n'~n"
+		     "-MiscArg10 \\~n\\\t~n"
 		     "#~n"
 		     "+\\#700~n"
+                     "#~s~n"
 		     "-extra +XtraArg6~n",
-	       [AFN2]),
+	       [AFN2,lists:duplicate(1024*1024, $a)]),
     write_file(AFN2,
 		     "-MiscArg3~n"
 		     "+\\#300~n"
 		     "-args_file ~s~n"
 		     "-MiscArg5~n"
-		     "+\\#500#anothercomment -MiscArg10~n"
+		     "+\\#500#anothercomment -MiscArg11~n"
 		     "-args_file ~s~n"
 		     "-args_file ~s~n"
 		     "-args_file ~s~n"
+                     "# ~s~n"
 		     "-extra +XtraArg5~n",
-		     [AFN3, AFN4, AFN5, AFN6]),
+		     [AFN3, AFN4, AFN5, AFN6,lists:duplicate(1758, $a)]),
     write_file(AFN3,
 		     "# comment again~n"
 		     " -MiscArg4 +\\#400 -extra +XtraArg1"),
@@ -156,33 +161,40 @@ args_file(Config) when is_list(Config) ->
     write_file(AFN6, "-extra # +XtraArg10~n"),
     CmdLine = "+#100 -MiscArg1 "
 	++ "-args_file " ++ AFN1
-	++ " +#800 -MiscArg8 -extra +XtraArg7 +XtraArg8",
+	++ " +#800 -MiscArgCLI \\\t -extra +XtraArg7 +XtraArg8",
     {Emu, Misc, Extra} = emu_args(CmdLine),
+    dbg:tracer(),dbg:p(self(),c),
+    dbg:tpl(?MODULE,verify_args, x),
+    dbg:tpl(?MODULE,verify_not_args, x),
     verify_args(["-#100", "-#200", "-#300", "-#400",
 		       "-#500", "-#600", "-#700", "-#800"], Emu),
     verify_args(["-MiscArg1", "-MiscArg2", "-MiscArg3", "-MiscArg4",
-		       "-MiscArg5", "-MiscArg6", "-MiscArg7", "-MiscArg8"],
+                 "-MiscArg5", "-MiscArg6", "-MiscArg7", "-MiscArg8",
+                 "val  with  double   space",
+                 "-MiscArg9","\n","-MiscArg10","\n\t","-MiscArgCLI"],
 		      Misc),
     verify_args(["+XtraArg1", "+XtraArg2", "+XtraArg3", "+XtraArg4",
 		       "+XtraArg5", "+XtraArg6", "+XtraArg7", "+XtraArg8"],
 		      Extra),
-    verify_not_args(["-MiscArg10", "-#1000", "+XtraArg10",
+    verify_not_args(["-MiscArg11", "-#1000", "+XtraArg10",
 			   "-MiscArg1", "-MiscArg2", "-MiscArg3", "-MiscArg4",
 			   "-MiscArg5", "-MiscArg6", "-MiscArg7", "-MiscArg8",
+                           "-MiscArg9", "-MiscArg10","-MiscArgCLI",
 			   "+XtraArg1", "+XtraArg2", "+XtraArg3", "+XtraArg4",
 			   "+XtraArg5", "+XtraArg6", "+XtraArg7", "+XtraArg8"],
 			  Emu),
-    verify_not_args(["-MiscArg10", "-#1000", "+XtraArg10",
+    verify_not_args(["-MiscArg11", "-#1000", "+XtraArg10",
 			   "-#100", "-#200", "-#300", "-#400",
 			   "-#500", "-#600", "-#700", "-#800",
 			   "+XtraArg1", "+XtraArg2", "+XtraArg3", "+XtraArg4",
 			   "+XtraArg5", "+XtraArg6", "+XtraArg7", "+XtraArg8"],
 			  Misc),
-    verify_not_args(["-MiscArg10", "-#1000", "+XtraArg10",
+    verify_not_args(["-MiscArg11", "-#1000", "+XtraArg10",
 			   "-#100", "-#200", "-#300", "-#400",
 			   "-#500", "-#600", "-#700", "-#800",
 			   "-MiscArg1", "-MiscArg2", "-MiscArg3", "-MiscArg4",
-			   "-MiscArg5", "-MiscArg6", "-MiscArg7", "-MiscArg8"],
+			   "-MiscArg5", "-MiscArg6", "-MiscArg7", "-MiscArg8",
+                           "-MiscArg9","-MiscArg10","-MiscArgCLI"],
 			  Extra),
     ok.
 
@@ -220,8 +232,7 @@ evil_args_file(Config) when is_list(Config) ->
 				ANums),
 		      Misc),
     ok.
-		      
-			  
+
 
 env(Config) when is_list(Config) ->
     os:putenv("ERL_AFLAGS", "-MiscArg1 +#100 -extra +XtraArg1 +XtraArg2"),
@@ -414,9 +425,9 @@ verify_not_args(Xs, Ys) ->
 emu_args(CmdLineArgs) ->
     io:format("CmdLineArgs = ~ts~n", [CmdLineArgs]),
     {ok,[[Erl]]} = init:get_argument(progname),
-    EmuCL = os:cmd(Erl ++ " -emu_args_exit " ++ CmdLineArgs),
-    io:format("EmuCL = ~ts", [EmuCL]),
-    split_emu_clt(string:lexemes(EmuCL, [$ ,$\t,$\n,[$\r,$\n]])).
+    EmuCL = os:cmd(Erl ++ " -emu_qouted_cmd_exit " ++ CmdLineArgs),
+    ct:pal("EmuCL = ~ts", [EmuCL]),
+    split_emu_clt(string:split(string:trim(EmuCL,both,"\n \""), "\" \"", all)).
 
 split_emu_clt(EmuCLT) ->
     split_emu_clt(EmuCLT, [], [], [], emu).
-- 
2.16.4

openSUSE Build Service is sponsored by