From 335c46b59888d431e5a57cddcf7ceecd09ec8e4a Mon Sep 17 00:00:00 2001 From: Zbigniew Jędrzejewski-Szmek Date: Sat, 24 Aug 2013 10:51:55 -0400 Subject: Disallow invalid UTF-8 configuration 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 | 88 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 31 deletions(-) diff --git a/src/shared/fileio.c b/src/shared/fileio.c index 2b1dab8053..77fd05955a 100644 --- a/src/shared/fileio.c +++ b/src/shared/fileio.c @@ -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); -- cgit v1.2.3-54-g00ecf