1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-25 23:21:33 +03:00

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.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2013-08-24 10:51:55 -04:00
parent fe05567c31
commit 335c46b598

View 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));
va_copy(aq, *ap);
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;
while ((k = va_arg(aq, const char *))) {
char **v;
va_copy(aq, *ap);
v = va_arg(aq, char **);
while ((k = va_arg(aq, const char *))) {
char **v;
if (streq(key, k)) {
va_end(aq);
free(*v);
*v = value;
return 1;
v = va_arg(aq, char **);
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);