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