]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MINOR: tools: ha_freearray() must also free the array master
authorAlexandre Laroche <larochealexandre@hotmail.com>
Wed, 11 Nov 2026 01:57:09 +0000 (20:57 -0500)
committerWilliam Lallemand <wlallemand@irq6.net>
Wed, 11 Nov 2026 12:20:07 +0000 (13:20 +0100)
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.

src/tools.c

index 7e4f7b4ea4e76257d424b832b68cb2ca030eb815..668fcfc00e717c5cf9cac4568ed64cea6c066f5d 100644 (file)
@@ -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;
  */
 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]);
        }
 
        for (i = 0; r && r[i]; i++) {
                ha_free(&r[i]);
        }
-       *array = NULL;
+       ha_free(array);
 }
 
 /*
 }
 
 /*