X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fconf-parser.c;h=a9b01135e6a1dfc7a3bcbd335b6d59c1a21cb7be;hp=970877650d642a269e27c8b2a28266c671646410;hb=34a35eced40860181757abe5ec00ac0e5d8d0225;hpb=f975e971accc4d50c73ae53167db3df7a7099cf2 diff --git a/src/conf-parser.c b/src/conf-parser.c index 970877650..a9b01135e 100644 --- a/src/conf-parser.c +++ b/src/conf-parser.c @@ -30,6 +30,7 @@ #include "macro.h" #include "strv.h" #include "log.h" +#include "utf8.h" int config_item_table_lookup( void *table, @@ -88,7 +89,8 @@ int config_item_perf_lookup( else { char *key; - if (asprintf(&key, "%s.%s", section, lvalue) < 0) + key = join(section, ".", lvalue, NULL); + if (!key) return -ENOMEM; p = lookup(key, strlen(key)); @@ -131,8 +133,12 @@ static int next_assignment( if (r < 0) return r; - if (func) - return func(filename, line, section, lvalue, ltype, rvalue, data, userdata); + if (r > 0) { + if (func) + return func(filename, line, section, lvalue, ltype, rvalue, data, userdata); + + return 0; + } /* Warn about unknown non-extension fields. */ if (!relaxed && !startswith(lvalue, "X-")) @@ -213,8 +219,13 @@ static int parse_line( return 0; } - if (sections && !*section) + if (sections && !*section) { + + if (!relaxed) + log_info("[%s:%u] Assignment outside of section. Ignoring.", filename, line); + return 0; + } e = strchr(l, '='); if (!e) { @@ -309,7 +320,7 @@ int config_parse( continuation = c; else { continuation = strdup(l); - if (!c) { + if (!continuation) { r = -ENOMEM; goto finish; } @@ -449,7 +460,7 @@ int config_parse_unsigned( return 0; } -int config_parse_size( +int config_parse_bytes_size( const char *filename, unsigned line, const char *section, @@ -460,20 +471,47 @@ int config_parse_size( void *userdata) { size_t *sz = data; - unsigned u; - int r; + off_t o; assert(filename); assert(lvalue); assert(rvalue); assert(data); - if ((r = safe_atou(rvalue, &u)) < 0) { - log_error("[%s:%u] Failed to parse numeric value, ignoring: %s", filename, line, rvalue); + if (parse_bytes(rvalue, &o) < 0 || (off_t) (size_t) o != o) { + log_error("[%s:%u] Failed to parse byte value, ignoring: %s", filename, line, rvalue); + return 0; + } + + *sz = (size_t) o; + return 0; +} + + +int config_parse_bytes_off( + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + off_t *bytes = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + assert_cc(sizeof(off_t) == sizeof(uint64_t)); + + if (parse_bytes(rvalue, bytes) < 0) { + log_error("[%s:%u] Failed to parse bytes value, ignoring: %s", filename, line, rvalue); return 0; } - *sz = (size_t) u; return 0; } @@ -504,6 +542,36 @@ int config_parse_bool( return 0; } +int config_parse_tristate( + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + + int k; + int *b = data; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + /* Tristates are like booleans, but can also take the 'default' value, i.e. "-1" */ + + k = parse_boolean(rvalue); + if (k < 0) { + log_error("[%s:%u] Failed to parse boolean value, ignoring: %s", filename, line, rvalue); + return 0; + } + + *b = !!k; + return 0; +} + int config_parse_string( const char *filename, unsigned line, @@ -522,14 +590,23 @@ int config_parse_string( assert(rvalue); assert(data); - if (*rvalue) { - if (!(n = strdup(rvalue))) - return -ENOMEM; - } else - n = NULL; + n = cunescape(rvalue); + if (!n) + return -ENOMEM; + + if (!utf8_is_valid(n)) { + log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue); + free(n); + return 0; + } free(*s); - *s = n; + if (*n) + *s = n; + else { + free(n); + *s = NULL; + } return 0; } @@ -552,12 +629,18 @@ int config_parse_path( assert(rvalue); assert(data); + if (!utf8_is_valid(rvalue)) { + log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue); + return 0; + } + if (!path_is_absolute(rvalue)) { log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue); return 0; } - if (!(n = strdup(rvalue))) + n = strdup(rvalue); + if (!n) return -ENOMEM; path_kill_slashes(n); @@ -584,6 +667,7 @@ int config_parse_strv( unsigned k; size_t l; char *state; + int r; assert(filename); assert(lvalue); @@ -594,7 +678,8 @@ int config_parse_strv( FOREACH_WORD_QUOTED(w, l, rvalue, state) k++; - if (!(n = new(char*, k+1))) + n = new(char*, k+1); + if (!n) return -ENOMEM; if (*sv) @@ -603,9 +688,21 @@ int config_parse_strv( else k = 0; - FOREACH_WORD_QUOTED(w, l, rvalue, state) - if (!(n[k++] = cunescape_length(w, l))) + FOREACH_WORD_QUOTED(w, l, rvalue, state) { + n[k] = cunescape_length(w, l); + if (!n[k]) { + r = -ENOMEM; goto fail; + } + + if (!utf8_is_valid(n[k])) { + log_error("[%s:%u] String is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue); + free(n[k]); + continue; + } + + k++; + } n[k] = NULL; free(*sv); @@ -618,7 +715,7 @@ fail: free(n[k-1]); free(n); - return -ENOMEM; + return r; } int config_parse_path_strv( @@ -648,7 +745,8 @@ int config_parse_path_strv( FOREACH_WORD_QUOTED(w, l, rvalue, state) k++; - if (!(n = new(char*, k+1))) + n = new(char*, k+1); + if (!n) return -ENOMEM; k = 0; @@ -657,11 +755,18 @@ int config_parse_path_strv( n[k] = (*sv)[k]; FOREACH_WORD_QUOTED(w, l, rvalue, state) { - if (!(n[k] = cunescape_length(w, l))) { + n[k] = strndup(w, l); + if (!n[k]) { r = -ENOMEM; goto fail; } + if (!utf8_is_valid(n[k])) { + log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue); + free(n[k]); + continue; + } + if (!path_is_absolute(n[k])) { log_error("[%s:%u] Not an absolute path, ignoring: %s", filename, line, rvalue); free(n[k]); @@ -669,7 +774,6 @@ int config_parse_path_strv( } path_kill_slashes(n[k]); - k++; } @@ -680,7 +784,6 @@ int config_parse_path_strv( return 0; fail: - free(n[k]); for (; k > 0; k--) free(n[k-1]); free(n);