Zbigniew Jędrzejewski-Szmek ca73a2
From e8321526823f2b7b945aeb04e5cdb1367e3d5b94 Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek ca73a2
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Zbigniew Jędrzejewski-Szmek ca73a2
Date: Fri, 17 Jan 2014 21:28:41 -0500
Zbigniew Jędrzejewski-Szmek ca73a2
Subject: [PATCH] core: do not print invalid utf-8 in error messages
Zbigniew Jędrzejewski-Szmek ca73a2
Zbigniew Jędrzejewski-Szmek ca73a2
Conflicts:
Zbigniew Jędrzejewski-Szmek ca73a2
	TODO
Zbigniew Jędrzejewski-Szmek ca73a2
---
Zbigniew Jędrzejewski-Szmek ca73a2
 src/shared/fileio.c  | 11 +++++++----
Zbigniew Jędrzejewski-Szmek ca73a2
 src/shared/utf8.c    | 26 ++++++++++++++++++++++++++
Zbigniew Jędrzejewski-Szmek ca73a2
 src/shared/utf8.h    |  3 +++
Zbigniew Jędrzejewski-Szmek ca73a2
 src/test/test-utf8.c | 17 +++++++++++++++++
Zbigniew Jędrzejewski-Szmek ca73a2
 4 files changed, 53 insertions(+), 4 deletions(-)
Zbigniew Jędrzejewski-Szmek ca73a2
Zbigniew Jędrzejewski-Szmek ca73a2
diff --git a/src/shared/fileio.c b/src/shared/fileio.c
Zbigniew Jędrzejewski-Szmek ca73a2
index d28e38a..121cd57 100644
Zbigniew Jędrzejewski-Szmek ca73a2
--- a/src/shared/fileio.c
Zbigniew Jędrzejewski-Szmek ca73a2
+++ b/src/shared/fileio.c
Zbigniew Jędrzejewski-Szmek ca73a2
@@ -467,15 +467,18 @@ static int parse_env_file_push(const char *filename, unsigned line,
Zbigniew Jędrzejewski-Szmek ca73a2
         va_list aq, *ap = userdata;
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
         if (!utf8_is_valid(key)) {
Zbigniew Jędrzejewski-Szmek ca73a2
-                log_error("%s:%u: invalid UTF-8 for key '%s', ignoring.",
Zbigniew Jędrzejewski-Szmek ca73a2
-                          filename, line, key);
Zbigniew Jędrzejewski-Szmek ca73a2
+                _cleanup_free_ char *p = utf8_escape_invalid(key);
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
+                log_error("%s:%u: invalid UTF-8 in key '%s', ignoring.",
Zbigniew Jędrzejewski-Szmek ca73a2
+                          filename, line, p);
Zbigniew Jędrzejewski-Szmek ca73a2
                 return -EINVAL;
Zbigniew Jędrzejewski-Szmek ca73a2
         }
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
         if (value && !utf8_is_valid(value)) {
Zbigniew Jędrzejewski-Szmek ca73a2
-                /* FIXME: filter UTF-8 */
Zbigniew Jędrzejewski-Szmek ca73a2
+                _cleanup_free_ char *p = utf8_escape_invalid(value);
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
                 log_error("%s:%u: invalid UTF-8 value for key %s: '%s', ignoring.",
Zbigniew Jędrzejewski-Szmek ca73a2
-                          filename, line, key, value);
Zbigniew Jędrzejewski-Szmek ca73a2
+                          filename, line, key, p);
Zbigniew Jędrzejewski-Szmek ca73a2
                 return -EINVAL;
Zbigniew Jędrzejewski-Szmek ca73a2
         }
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
diff --git a/src/shared/utf8.c b/src/shared/utf8.c
Zbigniew Jędrzejewski-Szmek ca73a2
index 31120af..2b70d45 100644
Zbigniew Jędrzejewski-Szmek ca73a2
--- a/src/shared/utf8.c
Zbigniew Jędrzejewski-Szmek ca73a2
+++ b/src/shared/utf8.c
Zbigniew Jędrzejewski-Szmek ca73a2
@@ -172,6 +172,32 @@ const char *utf8_is_valid(const char *str) {
Zbigniew Jędrzejewski-Szmek ca73a2
         return str;
Zbigniew Jędrzejewski-Szmek ca73a2
 }
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
+char *utf8_escape_invalid(const char *str) {
Zbigniew Jędrzejewski-Szmek ca73a2
+        char *p, *s;
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
+        assert(str);
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
+        p = s = malloc(strlen(str) * 4 + 1);
Zbigniew Jędrzejewski-Szmek ca73a2
+        if (!p)
Zbigniew Jędrzejewski-Szmek ca73a2
+                return NULL;
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
+        while (*str) {
Zbigniew Jędrzejewski-Szmek ca73a2
+                int len;
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
+                len = utf8_encoded_valid_unichar(str);
Zbigniew Jędrzejewski-Szmek ca73a2
+                if (len > 0) {
Zbigniew Jędrzejewski-Szmek ca73a2
+                        s = mempcpy(s, str, len);
Zbigniew Jędrzejewski-Szmek ca73a2
+                        str += len;
Zbigniew Jędrzejewski-Szmek ca73a2
+                } else {
Zbigniew Jędrzejewski-Szmek ca73a2
+                        s = mempcpy(s, UTF8_REPLACEMENT_CHARACTER, strlen(UTF8_REPLACEMENT_CHARACTER));
Zbigniew Jędrzejewski-Szmek ca73a2
+                        str += 1;
Zbigniew Jędrzejewski-Szmek ca73a2
+                }
Zbigniew Jędrzejewski-Szmek ca73a2
+        }
Zbigniew Jędrzejewski-Szmek ca73a2
+        *s = '\0';
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
+        return p;
Zbigniew Jędrzejewski-Szmek ca73a2
+}
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
 char *ascii_is_valid(const char *str) {
Zbigniew Jędrzejewski-Szmek ca73a2
         const char *p;
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
diff --git a/src/shared/utf8.h b/src/shared/utf8.h
Zbigniew Jędrzejewski-Szmek ca73a2
index 96a03ea..f93dfb8 100644
Zbigniew Jędrzejewski-Szmek ca73a2
--- a/src/shared/utf8.h
Zbigniew Jędrzejewski-Szmek ca73a2
+++ b/src/shared/utf8.h
Zbigniew Jędrzejewski-Szmek ca73a2
@@ -25,8 +25,11 @@
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
 #include "macro.h"
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
+#define UTF8_REPLACEMENT_CHARACTER "\xef\xbf\xbd"
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
 const char *utf8_is_valid(const char *s) _pure_;
Zbigniew Jędrzejewski-Szmek ca73a2
 char *ascii_is_valid(const char *s) _pure_;
Zbigniew Jędrzejewski-Szmek ca73a2
+char *utf8_escape_invalid(const char *s);
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
 bool utf8_is_printable(const char* str, size_t length) _pure_;
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
diff --git a/src/test/test-utf8.c b/src/test/test-utf8.c
Zbigniew Jędrzejewski-Szmek ca73a2
index f0182ee..53c1d47 100644
Zbigniew Jędrzejewski-Szmek ca73a2
--- a/src/test/test-utf8.c
Zbigniew Jędrzejewski-Szmek ca73a2
+++ b/src/test/test-utf8.c
Zbigniew Jędrzejewski-Szmek ca73a2
@@ -66,12 +66,29 @@ static void test_utf8_encoded_valid_unichar(void) {
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
 }
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
+static void test_utf8_escaping(void) {
Zbigniew Jędrzejewski-Szmek ca73a2
+        _cleanup_free_ char *p1, *p2, *p3;
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
+        p1 = utf8_escape_invalid("goo goo goo");
Zbigniew Jędrzejewski-Szmek ca73a2
+        puts(p1);
Zbigniew Jędrzejewski-Szmek ca73a2
+        assert_se(utf8_is_valid(p1));
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
+        p2 = utf8_escape_invalid("\341\204\341\204");
Zbigniew Jędrzejewski-Szmek ca73a2
+        puts(p2);
Zbigniew Jędrzejewski-Szmek ca73a2
+        assert_se(utf8_is_valid(p2));
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
+        p3 = utf8_escape_invalid("\341\204");
Zbigniew Jędrzejewski-Szmek ca73a2
+        puts(p3);
Zbigniew Jędrzejewski-Szmek ca73a2
+        assert_se(utf8_is_valid(p3));
Zbigniew Jędrzejewski-Szmek ca73a2
+}
Zbigniew Jędrzejewski-Szmek ca73a2
+
Zbigniew Jędrzejewski-Szmek ca73a2
 int main(int argc, char *argv[]) {
Zbigniew Jędrzejewski-Szmek ca73a2
         test_utf8_is_valid();
Zbigniew Jędrzejewski-Szmek ca73a2
         test_utf8_is_printable();
Zbigniew Jędrzejewski-Szmek ca73a2
         test_ascii_is_valid();
Zbigniew Jędrzejewski-Szmek ca73a2
         test_ascii_filter();
Zbigniew Jędrzejewski-Szmek ca73a2
         test_utf8_encoded_valid_unichar();
Zbigniew Jędrzejewski-Szmek ca73a2
+        test_utf8_escaping();
Zbigniew Jędrzejewski-Szmek ca73a2
 
Zbigniew Jędrzejewski-Szmek ca73a2
         return 0;
Zbigniew Jędrzejewski-Szmek ca73a2
 }