chiark / gitweb /
Disallow invalid UTF-8 configuration
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sat, 24 Aug 2013 14:51:55 +0000 (10:51 -0400)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 28 Aug 2013 12:04:56 +0000 (08:04 -0400)
It is best to catch such errors early. If invalid UTF-8 ends up being
given to dbus methods, the program will crash:

process 20801: arguments to dbus_message_iter_append_basic() were incorrect, assertion "_dbus_check_is_valid_utf8 (*string_p)" failed in file dbus-message.c line 2598.

src/shared/fileio.c

index 2b1dab8..77fd059 100644 (file)
@@ -23,6 +23,7 @@
 #include "fileio.h"
 #include "util.h"
 #include "strv.h"
+#include "utf8.h"
 
 int write_string_to_file(FILE *f, const char *line) {
         errno = 0;
@@ -177,13 +178,15 @@ int read_full_file(const char *fn, char **contents, size_t *size) {
 static int parse_env_file_internal(
                 const char *fname,
                 const char *newline,
-                int (*push) (const char *key, char *value, void *userdata),
+                int (*push) (const char *filename, unsigned line,
+                             const char *key, char *value, void *userdata),
                 void *userdata) {
 
         _cleanup_free_ char *contents = NULL, *key = NULL;
         size_t key_alloc = 0, n_key = 0, value_alloc = 0, n_value = 0, last_value_whitespace = (size_t) -1, last_key_whitespace = (size_t) -1;
         char *p, *value = NULL;
         int r;
+        unsigned line = 1;
 
         enum {
                 PRE_KEY,
@@ -230,6 +233,7 @@ static int parse_env_file_internal(
                 case KEY:
                         if (strchr(newline, c)) {
                                 state = PRE_KEY;
+                                line ++;
                                 n_key = 0;
                         } else if (c == '=') {
                                 state = PRE_VALUE;
@@ -253,6 +257,7 @@ static int parse_env_file_internal(
                 case PRE_VALUE:
                         if (strchr(newline, c)) {
                                 state = PRE_KEY;
+                                line ++;
                                 key[n_key] = 0;
 
                                 if (value)
@@ -262,7 +267,7 @@ static int parse_env_file_internal(
                                 if (last_key_whitespace != (size_t) -1)
                                         key[last_key_whitespace] = 0;
 
-                                r = push(key, value, userdata);
+                                r = push(fname, line, key, value, userdata);
                                 if (r < 0)
                                         goto fail;
 
@@ -292,6 +297,7 @@ static int parse_env_file_internal(
                 case VALUE:
                         if (strchr(newline, c)) {
                                 state = PRE_KEY;
+                                line ++;
 
                                 key[n_key] = 0;
 
@@ -306,7 +312,7 @@ static int parse_env_file_internal(
                                 if (last_key_whitespace != (size_t) -1)
                                         key[last_key_whitespace] = 0;
 
-                                r = push(key, value, userdata);
+                                r = push(fname, line, key, value, userdata);
                                 if (r < 0)
                                         goto fail;
 
@@ -408,8 +414,10 @@ static int parse_env_file_internal(
                 case COMMENT:
                         if (c == '\\')
                                 state = COMMENT_ESCAPE;
-                        else if (strchr(newline, c))
+                        else if (strchr(newline, c)) {
                                 state = PRE_KEY;
+                                line ++;
+                        }
                         break;
 
                 case COMMENT_ESCAPE:
@@ -439,7 +447,7 @@ static int parse_env_file_internal(
                 if (last_key_whitespace != (size_t) -1)
                         key[last_key_whitespace] = 0;
 
-                r = push(key, value, userdata);
+                r = push(fname, line, key, value, userdata);
                 if (r < 0)
                         goto fail;
         }
@@ -451,27 +459,36 @@ fail:
         return r;
 }
 
-static int parse_env_file_push(const char *key, char *value, void *userdata) {
-        const char *k;
-        va_list* ap = (va_list*) userdata;
-        va_list aq;
+static int parse_env_file_push(const char *filename, unsigned line,
+                               const char *key, char *value, void *userdata) {
+        assert(utf8_is_valid(key));
+
+        if (value && !utf8_is_valid(value))
+                /* FIXME: filter UTF-8 */
+                log_error("%s:%u: invalid UTF-8 for key %s: '%s', ignoring.",
+                          filename, line, key, value);
+        else {
+                const char *k;
+                va_list* ap = (va_list*) userdata;
+                va_list aq;
 
-        va_copy(aq, *ap);
+                va_copy(aq, *ap);
 
-        while ((k = va_arg(aq, const char *))) {
-                char **v;
+                while ((k = va_arg(aq, const char *))) {
+                        char **v;
 
-                v = va_arg(aq, char **);
+                        v = va_arg(aq, char **);
 
-                if (streq(key, k)) {
-                        va_end(aq);
-                        free(*v);
-                        *v = value;
-                        return 1;
+                        if (streq(key, k)) {
+                                va_end(aq);
+                                free(*v);
+                                *v = value;
+                                return 1;
+                        }
                 }
-        }
 
-        va_end(aq);
+                va_end(aq);
+        }
 
         free(value);
         return 0;
@@ -494,19 +511,28 @@ int parse_env_file(
         return r;
 }
 
-static int load_env_file_push(const char *key, char *value, void *userdata) {
-        char ***m = userdata;
-        char *p;
-        int r;
+static int load_env_file_push(const char *filename, unsigned line,
+                              const char *key, char *value, void *userdata) {
+        assert(utf8_is_valid(key));
 
-        p = strjoin(key, "=", strempty(value), NULL);
-        if (!p)
-                return -ENOMEM;
+        if (value && !utf8_is_valid(value))
+                /* FIXME: filter UTF-8 */
+                log_error("%s:%u: invalid UTF-8 for key %s: '%s', ignoring.",
+                          filename, line, key, value);
+        else {
+                char ***m = userdata;
+                char *p;
+                int r;
 
-        r = strv_push(m, p);
-        if (r < 0) {
-                free(p);
-                return r;
+                p = strjoin(key, "=", strempty(value), NULL);
+                if (!p)
+                        return -ENOMEM;
+
+                r = strv_push(m, p);
+                if (r < 0) {
+                        free(p);
+                        return r;
+                }
         }
 
         free(value);