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


Reply via email to