summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLuca Boccassi <bluca@debian.org>2023-03-02 17:33:16 +0000
committerGitHub <noreply@github.com>2023-03-02 17:33:16 +0000
commita41ac8ac407a1a58612059a45229f0d440f58e28 (patch)
treefc50476544799c51f34068077f2cc57c32cd465e /src
parentedd84b8e4b9db4dc57345ff97dfc7c22d8a6f241 (diff)
parent0b82a6fa5d2ba94bbc1c3db4a04dfd052e1cd446 (diff)
downloadsystemd-a41ac8ac407a1a58612059a45229f0d440f58e28.tar.gz
Merge pull request #26628 from msizanoen1/utf8-quote-valid
escape: Ensure that output is always valid UTF-8
Diffstat (limited to 'src')
-rw-r--r--src/basic/escape.c27
-rw-r--r--src/test/test-escape.c4
2 files changed, 24 insertions, 7 deletions
diff --git a/src/basic/escape.c b/src/basic/escape.c
index e04b435d5b..d2cb1c7320 100644
--- a/src/basic/escape.c
+++ b/src/basic/escape.c
@@ -473,15 +473,23 @@ char* octescape(const char *s, size_t len) {
static char* strcpy_backslash_escaped(char *t, const char *s, const char *bad) {
assert(bad);
+ assert(t);
+ assert(s);
+
+ while (*s) {
+ int l = utf8_encoded_valid_unichar(s, SIZE_MAX);
- for (; *s; s++)
- if (char_is_cc(*s))
- t += cescape_char(*s, t);
- else {
+ if (char_is_cc(*s) || l < 0)
+ t += cescape_char(*(s++), t);
+ else if (l == 1) {
if (*s == '\\' || strchr(bad, *s))
*(t++) = '\\';
- *(t++) = *s;
+ *(t++) = *(s++);
+ } else {
+ t = mempcpy(t, s, l);
+ s += l;
}
+ }
return t;
}
@@ -510,11 +518,16 @@ char* shell_maybe_quote(const char *s, ShellEscapeFlags flags) {
if (FLAGS_SET(flags, SHELL_ESCAPE_EMPTY) && isempty(s))
return strdup("\"\""); /* We don't use $'' here in the POSIX mode. "" is fine too. */
- for (p = s; *p; p++)
- if (char_is_cc(*p) ||
+ for (p = s; *p; ) {
+ int l = utf8_encoded_valid_unichar(p, SIZE_MAX);
+
+ if (char_is_cc(*p) || l < 0 ||
strchr(WHITESPACE SHELL_NEED_QUOTES, *p))
break;
+ p += l;
+ }
+
if (!*p)
return strdup(s);
diff --git a/src/test/test-escape.c b/src/test/test-escape.c
index b1ab5bab18..f3dd579e56 100644
--- a/src/test/test-escape.c
+++ b/src/test/test-escape.c
@@ -196,6 +196,10 @@ TEST(shell_maybe_quote) {
test_shell_maybe_quote_one("głąb\002\003rząd", 0, "\"głąb\\002\\003rząd\"");
test_shell_maybe_quote_one("głąb\002\003rząd", SHELL_ESCAPE_POSIX, "$'głąb\\002\\003rząd'");
+
+ /* Bogus UTF-8 strings */
+ test_shell_maybe_quote_one("\250\350", 0, "\"\\250\\350\"");
+ test_shell_maybe_quote_one("\250\350", SHELL_ESCAPE_POSIX, "$'\\250\\350'");
}
static void test_quote_command_line_one(char **argv, const char *expected) {