]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
conf-parser: check overflow in hashmap_find_free_section_line()
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 7 Sep 2023 20:11:57 +0000 (05:11 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 8 Sep 2023 03:55:44 +0000 (12:55 +0900)
Also, this also renames the function, and makes it optionally takes
a filename.

src/network/networkd-route.c
src/shared/conf-parser.c
src/shared/conf-parser.h

index 587bca2b26695b4f5e0a484472e518c7b674b4f8..6cefd3a9bf52f2d206674bed94f276b5569642d2 100644 (file)
@@ -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, &section_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, &section_line);
+        if (r < 0)
+                return r;
 
         /* DefaultRouteOnDevice= is in [Network] section. */
         r = route_new_static(network, network->filename, section_line, &n);
index 5476c061d7174d64880492c8032c8d0c3eb45c6f..7d51927845432868db9960f759be8edc2a8bd1d4 100644 (file)
@@ -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)                         \
index 3fc434ef03b850ff4110671ff97bb8eee5e4e159..74943523b346e57b98619f0594101e5b71c57b6c 100644 (file)
@@ -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. */