cfg_parse_peers previously leaked the contents of the `kws` string,
as it was unconditionally filled using bind_dump_kws, but only used
(and freed) within the error case.

Move the dumping into the error case to:
1. Ensure that the registered keywords are actually printed as least once.
2. The contents of kws are not leaked.

This move allows to narrow the scope of `kws`, so this is done as well.

This bug was found using valgrind:

    ==28217== 590 bytes in 1 blocks are definitely lost in loss record 51 of 71
    ==28217==    at 0x4C2DB8F: malloc (in 
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==28217==    by 0x4AD4C7: indent_msg (standard.c:3676)
    ==28217==    by 0x47E962: cfg_parse_peers (cfgparse.c:700)
    ==28217==    by 0x480273: readcfgfile (cfgparse.c:2147)
    ==28217==    by 0x479D51: init (haproxy.c:1585)
    ==28217==    by 0x404A02: main (haproxy.c:2585)

with this super simple configuration:

    peers peers
        bind :8081
        server A

This bug exists since the introduction of cfg_parse_peers in commit
355b2033ec0c89660db179b23d6f77b678d8c26d (which was introduced for HAProxy
2.0, but marked as backportable). It should be backported to all branches
containing that commit.
---
 src/cfgparse.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/src/cfgparse.c b/src/cfgparse.c
index 3188d50e8..181438ce7 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -616,7 +616,6 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
                static int kws_dumped;
                struct bind_conf *bind_conf;
                struct bind_kw *kw;
-               char *kws;
 
                cur_arg = 1;
 
@@ -693,13 +692,13 @@ int cfg_parse_peers(const char *file, int linenum, char 
**args, int kwm)
                        }
                        cur_arg += 1 + kw->skip;
                }
-               kws = NULL;
-               if (!kws_dumped) {
-                       kws_dumped = 1;
-                       bind_dump_kws(&kws);
-                       indent_msg(&kws, 4);
-               }
                if (*args[cur_arg] != 0) {
+                       char *kws = NULL;
+                       if (!kws_dumped) {
+                               kws_dumped = 1;
+                               bind_dump_kws(&kws);
+                               indent_msg(&kws, 4);
+                       }
                        ha_alert("parsing [%s:%d] : unknown keyword '%s' in 
'%s' section.%s%s\n",
                                 file, linenum, args[cur_arg], cursection,
                                 kws ? " Registered keywords :" : "", kws ? 
kws: "");
-- 
2.21.0


Reply via email to