Merge pull request #17027 from poettering/env-escape-fix
make sure we our env file writer, parser and shell agree on things
This commit is contained in:
commit
0c94a31464
|
@ -209,17 +209,21 @@ static int parse_env_file_internal(
|
|||
case DOUBLE_QUOTE_VALUE_ESCAPE:
|
||||
state = DOUBLE_QUOTE_VALUE;
|
||||
|
||||
if (c == '"') {
|
||||
if (strchr(SHELL_NEED_ESCAPE, c)) {
|
||||
/* If this is a char that needs escaping, just unescape it. */
|
||||
if (!GREEDY_REALLOC(value, value_alloc, n_value+2))
|
||||
return -ENOMEM;
|
||||
value[n_value++] = '"';
|
||||
} else if (!strchr(NEWLINE, c)) {
|
||||
value[n_value++] = c;
|
||||
} else if (c != '\n') {
|
||||
/* If other char than what needs escaping, keep the "\" in place, like the
|
||||
* real shell does. */
|
||||
if (!GREEDY_REALLOC(value, value_alloc, n_value+3))
|
||||
return -ENOMEM;
|
||||
value[n_value++] = '\\';
|
||||
value[n_value++] = c;
|
||||
}
|
||||
|
||||
/* Escaped newlines (aka "continuation lines") are eaten up entirely */
|
||||
break;
|
||||
|
||||
case COMMENT:
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "env-file.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "macro.h"
|
||||
#include "strv.h"
|
||||
|
@ -132,6 +133,46 @@ static void test_load_env_file_5(void) {
|
|||
assert_se(data[2] == NULL);
|
||||
}
|
||||
|
||||
static void test_write_and_load_env_file(void) {
|
||||
const char *v;
|
||||
|
||||
/* Make sure that our writer, parser and the shell agree on what our env var files mean */
|
||||
|
||||
FOREACH_STRING(v,
|
||||
"obbardc-laptop",
|
||||
"obbardc\\-laptop",
|
||||
"obbardc-lap\\top",
|
||||
"obbardc-lap\\top",
|
||||
"obbardc-lap\\\\top",
|
||||
"double\"quote",
|
||||
"single\'quote",
|
||||
"dollar$dollar",
|
||||
"newline\nnewline") {
|
||||
_cleanup_(unlink_and_freep) char *p = NULL;
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
_cleanup_free_ char *j = NULL, *w = NULL, *cmd = NULL, *from_shell = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
size_t sz;
|
||||
|
||||
assert_se(tempfn_random_child(NULL, NULL, &p) >= 0);
|
||||
|
||||
assert_se(j = strjoin("TEST=", v));
|
||||
assert_se(write_env_file(p, STRV_MAKE(j)) >= 0);
|
||||
|
||||
assert_se(cmd = strjoin(". ", p, " && /bin/echo -n \"$TEST\""));
|
||||
assert_se(f = popen(cmd, "re"));
|
||||
assert_se(read_full_stream(f, &from_shell, &sz) >= 0);
|
||||
assert_se(sz == strlen(v));
|
||||
assert_se(streq(from_shell, v));
|
||||
|
||||
assert_se(load_env_file(NULL, p, &l) >= 0);
|
||||
assert_se(strv_equal(l, STRV_MAKE(j)));
|
||||
|
||||
assert_se(parse_env_file(NULL, p, "TEST", &w) >= 0);
|
||||
assert_se(streq_ptr(w, v));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
test_setup_logging(LOG_INFO);
|
||||
|
||||
|
@ -140,4 +181,8 @@ int main(int argc, char *argv[]) {
|
|||
test_load_env_file_3();
|
||||
test_load_env_file_4();
|
||||
test_load_env_file_5();
|
||||
|
||||
test_write_and_load_env_file();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -151,6 +151,18 @@ static void test_parse_env_file(void) {
|
|||
assert_se(r >= 0);
|
||||
}
|
||||
|
||||
static void test_one_shell_var(const char *file, const char *variable, const char *value) {
|
||||
_cleanup_free_ char *cmd = NULL, *from_shell = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
size_t sz;
|
||||
|
||||
assert_se(cmd = strjoin(". ", file, " && /bin/echo -n \"$", variable, "\""));
|
||||
assert_se(f = popen(cmd, "re"));
|
||||
assert_se(read_full_stream(f, &from_shell, &sz) >= 0);
|
||||
assert_se(sz == strlen(value));
|
||||
assert_se(streq(from_shell, value));
|
||||
}
|
||||
|
||||
static void test_parse_multiline_env_file(void) {
|
||||
_cleanup_(unlink_tempfilep) char
|
||||
t[] = "/tmp/test-fileio-in-XXXXXX",
|
||||
|
@ -162,8 +174,8 @@ static void test_parse_multiline_env_file(void) {
|
|||
|
||||
assert_se(fmkostemp_safe(t, "w", &f) == 0);
|
||||
fputs("one=BAR\\\n"
|
||||
" VAR\\\n"
|
||||
"\tGAR\n"
|
||||
"\\ \\ \\ \\ VAR\\\n"
|
||||
"\\\tGAR\n"
|
||||
"#comment\n"
|
||||
"two=\"bar\\\n"
|
||||
" var\\\n"
|
||||
|
@ -173,9 +185,13 @@ static void test_parse_multiline_env_file(void) {
|
|||
" var \\\n"
|
||||
"\tgar \"\n", f);
|
||||
|
||||
fflush(f);
|
||||
assert_se(fflush_and_check(f) >= 0);
|
||||
fclose(f);
|
||||
|
||||
test_one_shell_var(t, "one", "BAR VAR\tGAR");
|
||||
test_one_shell_var(t, "two", "bar var\tgar");
|
||||
test_one_shell_var(t, "tri", "bar var \tgar ");
|
||||
|
||||
r = load_env_file(NULL, t, &a);
|
||||
assert_se(r >= 0);
|
||||
|
||||
|
|
Loading…
Reference in New Issue