hostname-setup: avoid O(N^2) string building in wildcard substitution

Building the result one char at a time via strextendn() is O(N^2)
because each call rescans and reallocs the buffer. With lines up to
LONG_LINE_MAX this caused a timeout in fuzz-hostname-setup. Use
GREEDY_REALLOC_APPEND to make it linear.

Fixes https://github.com/systemd/systemd/issues/42713
This commit is contained in:
Luca Boccassi
2026-06-24 18:49:25 +01:00
parent 84f6da603e
commit 1f9d56a7ab
+8 -5
View File
@@ -446,8 +446,7 @@ int hostname_substitute_wildcards(const char *name, char **ret) {
static const sd_id128_t key = SD_ID128_MAKE(98,10,ad,df,8d,7d,4f,b5,89,1b,4b,56,ac,c2,26,8f);
sd_id128_t mid = SD_ID128_NULL;
_cleanup_free_ char *result = NULL;
size_t left_bits = 0, counter = 0;
size_t word_pos = 0;
size_t left_bits = 0, counter = 0, word_pos = 0, n_result = 0;
uint64_t h = 0;
int r;
@@ -493,7 +492,7 @@ int hostname_substitute_wildcards(const char *name, char **ret) {
h >>= 4;
left_bits -= 4;
if (!strextendn(&result, &c, 1))
if (!GREEDY_REALLOC_APPEND(result, n_result, &c, 1))
return -ENOMEM;
} else if (*n == '$') {
@@ -504,13 +503,17 @@ int hostname_substitute_wildcards(const char *name, char **ret) {
if (r < 0)
return r;
if (!strextend(&result, w))
if (!GREEDY_REALLOC_APPEND(result, n_result, w, strlen(w)))
return -ENOMEM;
} else if (!strextendn(&result, n, 1))
} else if (!GREEDY_REALLOC_APPEND(result, n_result, n, 1))
return -ENOMEM;
}
if (!GREEDY_REALLOC(result, n_result + 1))
return -ENOMEM;
result[n_result] = 0;
*ret = TAKE_PTR(result);
return 0;
}