]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: arg: Fix leaks during arguments validation for fetches/converters
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 5 Aug 2020 21:07:07 +0000 (23:07 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 7 Aug 2020 12:25:21 +0000 (14:25 +0200)
Some sample fetches or sample converters uses a validation functions for their
arguments. In these function, string arguments (ARGT_STR) may be converted to
another type (for instance a regex, a variable or a integer). Because these
strings are allocated when the argument list is built, they must be freed after
a conversion. Most of time, it is done. But not always. This patch fixes these
minor memory leaks (only on few strings, during the configuration parsing).

This patch may be backported to all supported versions, most probably as far as
2.1 only. If this commit is backported, the previous one 73292e9e6 ("BUG/MINOR:
lua: Duplicate map name to load it when a new Map object is created") must also
be backported. Note that some validation functions does not exists on old
version. It should be easy to resolve conflicts.

src/map.c
src/payload.c
src/sample.c

index 3e9aa41b2b21d2e9894f4b990e21a78efbc88c95..5289e458a39e585e613ec7d3416fa052f1b291b2 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -151,6 +151,7 @@ int sample_load_map(struct arg *arg, struct sample_conv *conv,
                                  arg[1].data.str.area);
                        return 0;
                }
+               free(arg[1].data.str.area);
                if (data.type == SMP_T_IPV4) {
                        arg[1].type = ARGT_IPV4;
                        arg[1].data.ipv4 = data.u.ipv4;
@@ -161,6 +162,7 @@ int sample_load_map(struct arg *arg, struct sample_conv *conv,
        }
 
        /* replace the first argument by this definition */
+       free(arg[0].data.str.area);
        arg[0].type = ARGT_MAP;
        arg[0].data.map = desc;
 
index 7feea16c302c3093634bc8e64334207ffe75ea81..a977233de0d9c80973a7e7b63f48ce9fe87add6f 100644 (file)
@@ -1102,17 +1102,21 @@ int val_payload_lv(struct arg *arg, char **err_msg)
        }
 
        if (arg[2].type == ARGT_STR && arg[2].data.str.data > 0) {
+               long long int i;
+
                if (arg[2].data.str.area[0] == '+' || arg[2].data.str.area[0] == '-')
                        relative = 1;
                str = arg[2].data.str.area;
-               arg[2].type = ARGT_SINT;
-               arg[2].data.sint = read_int64(&str,
-                                             str + arg[2].data.str.data);
+               i = read_int64(&str, str + arg[2].data.str.data);
                if (*str != '\0') {
                        memprintf(err_msg, "payload offset2 is not a number");
                        return 0;
                }
-          if (arg[0].data.sint + arg[1].data.sint + arg[2].data.sint < 0) {
+               free(arg[2].data.str.area);
+               arg[2].type = ARGT_SINT;
+               arg[2].data.sint = i;
+
+               if (arg[0].data.sint + arg[1].data.sint + arg[2].data.sint < 0) {
                        memprintf(err_msg, "payload offset2 too negative");
                        return 0;
                }
@@ -1310,6 +1314,7 @@ int val_distcc(struct arg *arg, char **err_msg)
        token = (arg[0].data.str.area[0] << 24) + (arg[0].data.str.area[1] << 16) +
                (arg[0].data.str.area[2] << 8) + (arg[0].data.str.area[3] << 0);
 
+       free(arg[0].data.str.area);
        arg[0].type      = ARGT_SINT;
        arg[0].data.sint = token;
 
index 2e221047b5fd1a5f7512feca1a70066f95ababa3..9026b6e9c9f635ae422c232a221f0a5baae2c484 100644 (file)
@@ -1514,6 +1514,7 @@ static int smp_check_debug(struct arg *args, struct sample_conv *conv,
                return 0;
        }
 
+       free(args[1].data.str.area);
        args[1].type = ARGT_PTR;
        args[1].data.ptr = sink;
        return 1;
@@ -2143,6 +2144,8 @@ enum input_type {
 static int sample_conv_json_check(struct arg *arg, struct sample_conv *conv,
                                   const char *file, int line, char **err)
 {
+       enum input_type type;
+
        if (!arg) {
                memprintf(err, "Unexpected empty arg list");
                return 0;
@@ -2153,45 +2156,28 @@ static int sample_conv_json_check(struct arg *arg, struct sample_conv *conv,
                return 0;
        }
 
-       if (strcmp(arg->data.str.area, "") == 0) {
-               arg->type = ARGT_SINT;
-               arg->data.sint = IT_ASCII;
-               return 1;
-       }
-
-       else if (strcmp(arg->data.str.area, "ascii") == 0) {
-               arg->type = ARGT_SINT;
-               arg->data.sint = IT_ASCII;
-               return 1;
-       }
-
-       else if (strcmp(arg->data.str.area, "utf8") == 0) {
-               arg->type = ARGT_SINT;
-               arg->data.sint = IT_UTF8;
-               return 1;
-       }
-
-       else if (strcmp(arg->data.str.area, "utf8s") == 0) {
-               arg->type = ARGT_SINT;
-               arg->data.sint = IT_UTF8S;
-               return 1;
-       }
-
-       else if (strcmp(arg->data.str.area, "utf8p") == 0) {
-               arg->type = ARGT_SINT;
-               arg->data.sint = IT_UTF8P;
-               return 1;
-       }
-
-       else if (strcmp(arg->data.str.area, "utf8ps") == 0) {
-               arg->type = ARGT_SINT;
-               arg->data.sint = IT_UTF8PS;
-               return 1;
+       if (strcmp(arg->data.str.area, "") == 0)
+               type = IT_ASCII;
+       else if (strcmp(arg->data.str.area, "ascii") == 0)
+               type = IT_ASCII;
+       else if (strcmp(arg->data.str.area, "utf8") == 0)
+               type = IT_UTF8;
+       else if (strcmp(arg->data.str.area, "utf8s") == 0)
+               type = IT_UTF8S;
+       else if (strcmp(arg->data.str.area, "utf8p") == 0)
+               type = IT_UTF8P;
+       else if (strcmp(arg->data.str.area, "utf8ps") == 0)
+               type = IT_UTF8PS;
+       else {
+               memprintf(err, "Unexpected input code type. "
+                         "Allowed value are 'ascii', 'utf8', 'utf8s', 'utf8p' and 'utf8ps'");
+               return 0;
        }
 
-       memprintf(err, "Unexpected input code type. "
-                      "Allowed value are 'ascii', 'utf8', 'utf8s', 'utf8p' and 'utf8ps'");
-       return 0;
+       free(arg->data.str.area);
+       arg->type = ARGT_SINT;
+       arg->data.sint = type;
+       return 1;
 }
 
 static int sample_conv_json(const struct arg *arg_p, struct sample *smp, void *private)
@@ -2666,6 +2652,7 @@ static int check_operator(struct arg *args, struct sample_conv *conv,
 {
        const char *str;
        const char *end;
+       long long int i;
 
        /* Try to decode a variable. */
        if (vars_check_arg(&args[0], NULL))
@@ -2674,12 +2661,15 @@ static int check_operator(struct arg *args, struct sample_conv *conv,
        /* Try to convert an integer */
        str = args[0].data.str.area;
        end = str + strlen(str);
-       args[0].data.sint = read_int64(&str, end);
+       i = read_int64(&str, end);
        if (*str != '\0') {
                memprintf(err, "expects an integer or a variable name");
                return 0;
        }
+
+       free(args[0].data.str.area);
        args[0].type = ARGT_SINT;
+       args[0].data.sint = i;
        return 1;
 }
 
@@ -3203,6 +3193,7 @@ static int sample_conv_protobuf_check(struct arg *args, struct sample_conv *conv
                        return 0;
                }
 
+               free(args[1].data.str.area);
                args[1].type = ARGT_SINT;
                args[1].data.sint = pbuf_type;
        }
@@ -3368,23 +3359,26 @@ smp_fetch_env(const struct arg *args, struct sample *smp, const char *kw, void *
 int smp_check_date_unit(struct arg *args, char **err)
 {
         if (args[1].type == ARGT_STR) {
+               long long int unit;
+
                 if (strcmp(args[1].data.str.area, "s") == 0) {
-                        args[1].data.sint = TIME_UNIT_S;
+                        unit = TIME_UNIT_S;
                 }
                 else if (strcmp(args[1].data.str.area, "ms") == 0) {
-                        args[1].data.sint = TIME_UNIT_MS;
+                        unit = TIME_UNIT_MS;
                 }
                 else if (strcmp(args[1].data.str.area, "us") == 0) {
-                        args[1].data.sint = TIME_UNIT_US;
+                        unit = TIME_UNIT_US;
                 }
                 else {
                         memprintf(err, "expects 's', 'ms' or 'us', got '%s'",
                                   args[1].data.str.area);
                         return 0;
                 }
-                free(args[1].data.str.area);
-                args[1].data.str.area = NULL;
+
+               free(args[1].data.str.area);
                 args[1].type = ARGT_SINT;
+               args[1].data.sint = unit;
         }
         else if (args[1].type != ARGT_STOP) {
                 memprintf(err, "Unexpected arg type");
@@ -3622,6 +3616,7 @@ static int smp_check_const_bin(struct arg *args, char **err)
 
        if (!parse_binary(args[0].data.str.area, &binstr, &binstrlen, err))
                return 0;
+       free(args[0].data.str.area);
        args[0].type = ARGT_STR;
        args[0].data.str.area = binstr;
        args[0].data.str.data = binstrlen;