From: Yu Watanabe Date: Thu, 7 Sep 2023 20:11:57 +0000 (+0900) Subject: conf-parser: check overflow in hashmap_find_free_section_line() X-Git-Tag: v255-rc1~548^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d9171a230deae234c5e19708c027883434a05fbc;p=thirdparty%2Fsystemd.git conf-parser: check overflow in hashmap_find_free_section_line() Also, this also renames the function, and makes it optionally takes a filename. --- diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 587bca2b266..6cefd3a9bf5 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -1945,7 +1945,9 @@ int network_add_ipv4ll_route(Network *network) { if (!network->ipv4ll_route) return 0; - section_line = hashmap_find_free_section_line(network->routes_by_section); + r = hashmap_by_section_find_unused_line(network->routes_by_section, network->filename, §ion_line); + if (r < 0) + return r; /* IPv4LLRoute= is in [Network] section. */ r = route_new_static(network, network->filename, section_line, &n); @@ -1978,7 +1980,9 @@ int network_add_default_route_on_device(Network *network) { if (!network->default_route_on_device) return 0; - section_line = hashmap_find_free_section_line(network->routes_by_section); + r = hashmap_by_section_find_unused_line(network->routes_by_section, network->filename, §ion_line); + if (r < 0) + return r; /* DefaultRouteOnDevice= is in [Network] section. */ r = route_new_static(network, network->filename, section_line, &n); diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index 5476c061d71..7d519278454 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -766,16 +766,27 @@ int config_section_new(const char *filename, unsigned line, ConfigSection **ret) return 0; } -unsigned hashmap_find_free_section_line(Hashmap *hashmap) { +int hashmap_by_section_find_unused_line( + Hashmap *entries_by_section, + const char *filename, + unsigned *ret) { + ConfigSection *cs; unsigned n = 0; void *entry; - HASHMAP_FOREACH_KEY(entry, cs, hashmap) - if (n < cs->line) - n = cs->line; + HASHMAP_FOREACH_KEY(entry, cs, entries_by_section) { + if (filename && !streq(cs->filename, filename)) + continue; + n = MAX(n, cs->line); + } + + /* overflow? */ + if (n >= UINT_MAX) + return -EFBIG; - return n + 1; + *ret = n + 1; + return 0; } #define DEFINE_PARSER(type, vartype, conv_func) \ diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h index 3fc434ef03b..74943523b34 100644 --- a/src/shared/conf-parser.h +++ b/src/shared/conf-parser.h @@ -138,7 +138,10 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(ConfigSection*, config_section_free); int config_section_new(const char *filename, unsigned line, ConfigSection **ret); extern const struct hash_ops config_section_hash_ops; -unsigned hashmap_find_free_section_line(Hashmap *hashmap); +int hashmap_by_section_find_unused_line( + Hashmap *entries_by_section, + const char *filename, + unsigned *ret); static inline bool section_is_invalid(ConfigSection *section) { /* If this returns false, then it does _not_ mean the section is valid. */