From: Alexandre Laroche Date: Wed, 11 Nov 2026 01:57:09 +0000 (-0500) Subject: BUG/MINOR: tools: ha_freearray() must also free the array X-Git-Url: https://git.kaiwu.me/$%7BISSUES%7D/static/gitweb.js?a=commitdiff_plain;ds=sidebyside;p=haproxy.git BUG/MINOR: tools: ha_freearray() must also free the array ha_freearray() frees each string of a NULL-terminated array and then sets the array pointer to NULL, but never frees the array itself. Its only caller is ckch_conf_parse(), which uses it to release the previous value when a PARSE_TYPE_ARRAY_SUBSTR keyword ("domains", "ips") is specified twice on the same line, as in: crt-store s load crt site.pem domains "a.example,b.example" domains "c.example" The strings are freed but the array of the first value is leaked (24 bytes here, reported by LeakSanitizer with "haproxy -c -d" on a build with -fsanitize=address). The leak only happens when parsing a line with a duplicated keyword, which also emits an "already specified, overwriting" warning, so the impact is minimal. Fix it by freeing the array with ha_free(), which also sets the pointer to NULL as before. With the patch, the same configuration with either "domains" or "ips" repeated reports no leak. Also accept a NULL array argument without dereferencing it. An argument pointing to a NULL array remains safe, and non-NULL arrays are still fully freed and their pointer cleared. Fixes issue #3569. This was introduced by commit 96b1f1fd2 ("MINOR: tools: ha_freearray() frees an array of string") together with its use in commit 9c0c05b7b ("BUG/MINOR: ssl/ckch: always ha_freearray() the previous entry during parsing"), both in 3.2-dev16, so this must be backported to 3.2. --- diff --git a/src/tools.c b/src/tools.c index 7e4f7b4ea..668fcfc00 100644 --- a/src/tools.c +++ b/src/tools.c @@ -7772,18 +7772,23 @@ out: } /* - * free() an array of strings terminated by a NULL entry - * set the pointer to NULL + * Free a NULL-terminated array of strings, including the array itself, + * and set the pointer to NULL. Both array == NULL and *array == NULL are safe. */ void ha_freearray(char ***array) { int i; - char **r = *array; + char **r; + + if (!array) + return; + + r = *array; for (i = 0; r && r[i]; i++) { ha_free(&r[i]); } - *array = NULL; + ha_free(array); } /*