summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO3
-rw-r--r--src/shared/fileio.c11
-rw-r--r--src/shared/utf8.c26
-rw-r--r--src/shared/utf8.h3
-rw-r--r--src/test/test-utf8.c17
5 files changed, 53 insertions, 7 deletions
diff --git a/TODO b/TODO
index 57e82ff262..1a1e889319 100644
--- a/TODO
+++ b/TODO
@@ -16,9 +16,6 @@ Bugfixes:
* properly handle .mount unit state tracking when two mount points are stacked one on top of another on the exact same mount point.
-* When we detect invalid UTF-8, we cannot use it in an error message:
- log...("Path is not UTF-8 clean, ignoring assignment: %s", rvalue);
-
* shorten the message to sane length:
Cannot add dependency job for unit display-manager.service, ignoring: Unit display-manager.service failed to load: No such file or directory. See system logs and 'systemctl status display-manager.service' for details.
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
index 838d128433..b81eeb272a 100644
--- a/src/shared/fileio.c
+++ b/src/shared/fileio.c
@@ -539,15 +539,18 @@ static int parse_env_file_push(const char *filename, unsigned line,
va_list aq, *ap = userdata;
if (!utf8_is_valid(key)) {
- log_error("%s:%u: invalid UTF-8 for key '%s', ignoring.",
- filename, line, key);
+ _cleanup_free_ char *p = utf8_escape_invalid(key);
+
+ log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.",
+ filename, line, p);
return -EINVAL;
}
if (value && !utf8_is_valid(value)) {
- /* FIXME: filter UTF-8 */
+ _cleanup_free_ char *p = utf8_escape_invalid(value);
+
log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.",
- filename, line, key, value);
+ filename, line, key, p);
return -EINVAL;
}
diff --git a/src/shared/utf8.c b/src/shared/utf8.c
index 6e5ba9abf4..0b524d8a90 100644
--- a/src/shared/utf8.c
+++ b/src/shared/utf8.c
@@ -174,6 +174,32 @@ const char *utf8_is_valid(const char *str) {
return str;
}
+char *utf8_escape_invalid(const char *str) {
+ char *p, *s;
+
+ assert(str);
+
+ p = s = malloc(strlen(str) * 4 + 1);
+ if (!p)
+ return NULL;
+
+ while (*str) {
+ int len;
+
+ len = utf8_encoded_valid_unichar(str);
+ if (len > 0) {
+ s = mempcpy(s, str, len);
+ str += len;
+ } else {
+ s = mempcpy(s, UTF8_REPLACEMENT_CHARACTER, strlen(UTF8_REPLACEMENT_CHARACTER));
+ str += 1;
+ }
+ }
+ *s = '\0';
+
+ return p;
+}
+
char *ascii_is_valid(const char *str) {
const char *p;
diff --git a/src/shared/utf8.h b/src/shared/utf8.h
index f56077438a..c0eb73a21d 100644
--- a/src/shared/utf8.h
+++ b/src/shared/utf8.h
@@ -25,8 +25,11 @@
#include "macro.h"
+#define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
+
const char *utf8_is_valid(const char *s) _pure_;
char *ascii_is_valid(const char *s) _pure_;
+char *utf8_escape_invalid(const char *s);
bool utf8_is_printable(const char* str, size_t length) _pure_;
diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c
index d2198fdc74..b7d988f22d 100644
--- a/src/test/test-utf8.c
+++ b/src/test/test-utf8.c
@@ -50,11 +50,28 @@ static void test_utf8_encoded_valid_unichar(void) {
}
+static void test_utf8_escaping(void) {
+ _cleanup_free_ char *p1, *p2, *p3;
+
+ p1 = utf8_escape_invalid("goo goo goo");
+ puts(p1);
+ assert_se(utf8_is_valid(p1));
+
+ p2 = utf8_escape_invalid("\341\204\341\204");
+ puts(p2);
+ assert_se(utf8_is_valid(p2));
+
+ p3 = utf8_escape_invalid("\341\204");
+ puts(p3);
+ assert_se(utf8_is_valid(p3));
+}
+
int main(int argc, char *argv[]) {
test_utf8_is_valid();
test_utf8_is_printable();
test_ascii_is_valid();
test_utf8_encoded_valid_unichar();
+ test_utf8_escaping();
return 0;
}