Instead of just calling release_sample_arg(conv_expr->arg_p) we also must free() the conv_expr itself (after removing it from the list).
Given the following example configuration: frontend foo bind *:8080 mode http http-request set-var(txn.foo) str(bar) acl is_match str(foo),strcmp(txn.hash) -m bool Running a configuration check within valgrind reports: ==1431== 32 bytes in 1 blocks are definitely lost in loss record 20 of 43 ==1431== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==1431== by 0x4C39B5: sample_parse_expr (sample.c:982) ==1431== by 0x56B410: parse_acl_expr (acl.c:319) ==1431== by 0x56BA7F: parse_acl (acl.c:697) ==1431== by 0x48D225: cfg_parse_listen (cfgparse-listen.c:816) ==1431== by 0x4797C3: readcfgfile (cfgparse.c:2167) ==1431== by 0x52943D: init (haproxy.c:2021) ==1431== by 0x41F382: main (haproxy.c:3133) After this patch is applied the leak is gone as expected. This is a fairly minor leak that can only be observed if samples need to be freed, which is not something that should occur during normal processing and most likely only during shut down. Thus no backport should be needed. --- src/sample.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sample.c b/src/sample.c index faf6471c0..a6633e849 100644 --- a/src/sample.c +++ b/src/sample.c @@ -1424,8 +1424,12 @@ void release_sample_expr(struct sample_expr *expr) if (!expr) return; - list_for_each_entry_safe(conv_expr, conv_exprb, &expr->conv_exprs, list) + list_for_each_entry_safe(conv_expr, conv_exprb, &expr->conv_exprs, list) { + LIST_DEL(&conv_expr->list); release_sample_arg(conv_expr->arg_p); + free(conv_expr); + } + release_sample_arg(expr->arg_p); free(expr); } -- 2.27.0