]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: sample: make sample_parse_expr() able to return an end pointer
authorWilly Tarreau <w@1wt.eu>
Fri, 14 Feb 2020 15:50:14 +0000 (16:50 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 14 Feb 2020 18:02:06 +0000 (19:02 +0100)
When an end pointer is passed, instead of complaining that a comma is
missing after a keyword, sample_parse_expr() will silently return the
pointer to the current location into this return pointer so that the
caller can continue its parsing. This will be used by more complex
expressions which embed sample expressions, and may even permit to
embed sample expressions into arguments of other expressions.

14 files changed:
include/proto/sample.h
src/acl.c
src/cfgparse-listen.c
src/dns.c
src/flt_spoe.c
src/http_act.c
src/log.c
src/proto_tcp.c
src/queue.c
src/sample.c
src/server.c
src/stick_table.c
src/tcp_rules.c
src/vars.c

index f0be3fd208eaec6ee71f2c497530d85dc2240aff..b4d52c5ea4139d3f359c2218ba7b34c7fba4fbbd 100644 (file)
@@ -28,7 +28,7 @@
 
 extern const char *smp_to_type[SMP_TYPES];
 
-struct sample_expr *sample_parse_expr(char **str, int *idx, const char *file, int line, char **err, struct arg_list *al);
+struct sample_expr *sample_parse_expr(char **str, int *idx, const char *file, int line, char **err, struct arg_list *al, char **endptr);
 struct sample_conv *find_sample_conv(const char *kw, int len);
 struct sample *sample_process(struct proxy *px, struct session *sess,
                               struct stream *strm, unsigned int opt,
index 4b8a6d49a57979ce92aa6369b07a1919394e86e0..1e32271bea250a9cad5fa0c199fbc9e0131d5c07 100644 (file)
--- a/src/acl.c
+++ b/src/acl.c
@@ -321,7 +321,7 @@ struct acl_expr *parse_acl_expr(const char **args, char **err, struct arg_list *
                 * so, we retrieve a completely parsed expression with args and
                 * convs already done.
                 */
-               smp = sample_parse_expr((char **)args, &idx, file, line, err, al);
+               smp = sample_parse_expr((char **)args, &idx, file, line, err, al, NULL);
                if (!smp) {
                        memprintf(err, "%s in ACL expression '%s'", *err, *args);
                        goto out_return;
index 6d9c1f52e6b000516ba27436c2280f1625641efa..3c2978c8ae21069e4921f5bb52b3b364543b7d43 100644 (file)
@@ -1727,7 +1727,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
                }
 
                curproxy->conf.args.ctx = ARGC_STK;
-               expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
+               expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args, NULL);
                if (!expr) {
                        ha_alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
                        err_code |= ERR_ALERT | ERR_FATAL;
index f8230185778506a460edb68d6175cd9c0fe3e9f9..86147a4170dfd259ffc004deffa5261d96630a7a 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -2572,7 +2572,7 @@ enum act_parse_ret dns_parse_do_resolve(const char **args, int *orig_arg, struct
 
        cur_arg = cur_arg + 1;
 
-       expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args);
+       expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args, NULL);
        if (!expr)
                goto do_resolve_parse_error;
 
index 4e448dd1124697375b3236382768947d5b2461fb..a78e6159e71b3e0d53c38321813f30b00538395b 100644 (file)
@@ -3968,7 +3968,7 @@ cfg_parse_spoe_message(const char *file, int linenum, char **args, int kwm)
                        }
                        arg->expr = sample_parse_expr((char*[]){delim, NULL},
                                                      &idx, file, linenum, &errmsg,
-                                                     &curproxy->conf.args);
+                                                     &curproxy->conf.args, NULL);
                        if (arg->expr == NULL) {
                                ha_alert("parsing [%s:%d] : '%s': %s.\n", file, linenum, args[0], errmsg);
                                err_code |= ERR_ALERT | ERR_FATAL;
index 4c0c5c4066e1679316091118e17784e52ca596b8..718501416589726f18689398f25350f7f485318a 100644 (file)
@@ -558,7 +558,7 @@ static enum act_parse_ret parse_http_req_capture(const char **args, int *orig_ar
        }
 
        cur_arg = *orig_arg;
-       expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args);
+       expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args, NULL);
        if (!expr)
                return ACT_RET_PRS_ERR;
 
@@ -743,7 +743,7 @@ static enum act_parse_ret parse_http_res_capture(const char **args, int *orig_ar
        }
 
        cur_arg = *orig_arg;
-       expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args);
+       expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args, NULL);
        if (!expr)
                return ACT_RET_PRS_ERR;
 
@@ -1730,7 +1730,7 @@ static enum act_parse_ret parse_http_track_sc(const char **args, int *orig_arg,
 
        cur_arg = *orig_arg;
        expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line,
-                                err, &px->conf.args);
+                                err, &px->conf.args, NULL);
        if (!expr)
                return ACT_RET_PRS_ERR;
 
index 23e6c475757cca042a0f19e6ba87cdbf1258a9e3..51d684d6e746a0db828e150515ce7699ddc07ca2 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -488,7 +488,7 @@ int add_sample_to_logformat_list(char *text, char *arg, int arg_len, struct prox
        cmd[1] = "";
        cmd_arg = 0;
 
-       expr = sample_parse_expr(cmd, &cmd_arg, curpx->conf.args.file, curpx->conf.args.line, err, &curpx->conf.args);
+       expr = sample_parse_expr(cmd, &cmd_arg, curpx->conf.args.file, curpx->conf.args.line, err, &curpx->conf.args, NULL);
        if (!expr) {
                memprintf(err, "failed to parse sample expression <%s> : %s", text, *err);
                goto error_free;
index 7668ec29c37895b39961321a620897aee0070b7b..8486863a2f942d8a6c03193f01d315e7240a9dfd 100644 (file)
@@ -1287,7 +1287,7 @@ enum act_parse_ret tcp_parse_set_src_dst(const char **args, int *orig_arg, struc
        unsigned int where;
 
        cur_arg = *orig_arg;
-       expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args);
+       expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args, NULL);
        if (!expr)
                return ACT_RET_PRS_ERR;
 
index 1bb08a51315f6ed918464ee65b46d20a0e675494..9fd3e9d155ceb4e2ccdfb82d1c26b4ff63b902ef 100644 (file)
@@ -544,7 +544,7 @@ static enum act_parse_ret parse_set_priority_class(const char **args, int *arg,
        unsigned int where = 0;
 
        rule->arg.expr = sample_parse_expr((char **)args, arg, px->conf.args.file,
-                                          px->conf.args.line, err, &px->conf.args);
+                                          px->conf.args.line, err, &px->conf.args, NULL);
        if (!rule->arg.expr)
                return ACT_RET_PRS_ERR;
 
@@ -572,7 +572,7 @@ static enum act_parse_ret parse_set_priority_offset(const char **args, int *arg,
        unsigned int where = 0;
 
        rule->arg.expr = sample_parse_expr((char **)args, arg, px->conf.args.file,
-                                          px->conf.args.line, err, &px->conf.args);
+                                          px->conf.args.line, err, &px->conf.args, NULL);
        if (!rule->arg.expr)
                return ACT_RET_PRS_ERR;
 
index d82451fc3fa521f5efd230144a4a809a4f7daf5f..ef0f7b00cb728ccd9ae37d7e9ae62cd708ce4415 100644 (file)
@@ -824,8 +824,11 @@ sample_cast_fct sample_casts[SMP_TYPES][SMP_TYPES] = {
  *        fetch keyword followed by format conversion keywords.
  * Returns a pointer on allocated sample expression structure.
  * The caller must have set al->ctx.
+ * If <endptr> is non-nul, it will be set to the first unparsed character
+ * (which may be the final '\0') on success. If it is nul, the expression
+ * must be properly terminated by a '\0' otherwise an error is reported.
  */
-struct sample_expr *sample_parse_expr(char **str, int *idx, const char *file, int line, char **err_msg, struct arg_list *al)
+struct sample_expr *sample_parse_expr(char **str, int *idx, const char *file, int line, char **err_msg, struct arg_list *al, char **endptr)
 {
        const char *begw; /* beginning of word */
        const char *endw; /* end of word */
@@ -917,6 +920,10 @@ struct sample_expr *sample_parse_expr(char **str, int *idx, const char *file, in
                int argcnt;
 
                if (*endt && *endt != ',') {
+                       if (endptr) {
+                               /* end found, let's stop here */
+                               break;
+                       }
                        if (ckw)
                                memprintf(err_msg, "missing comma after converter '%s'", ckw);
                        else
@@ -949,8 +956,10 @@ struct sample_expr *sample_parse_expr(char **str, int *idx, const char *file, in
                conv = find_sample_conv(begw, endw - begw);
                if (!conv) {
                        /* we found an isolated keyword that we don't know, it's not ours */
-                       if (begw == str[*idx])
+                       if (begw == str[*idx]) {
+                               endt = begw;
                                break;
+                       }
                        memprintf(err_msg, "unknown converter '%s'", ckw);
                        goto out_error;
                }
@@ -996,6 +1005,11 @@ struct sample_expr *sample_parse_expr(char **str, int *idx, const char *file, in
                }
        }
 
+       if (endptr) {
+               /* end found, let's stop here */
+               *endptr = (char *)endt;
+       }
+
  out:
        free(fkw);
        free(ckw);
index d7cb97d9abb7838de457656667109d4677cb7339..959fb22e749de396b2cb02c099c93440052e6b71 100644 (file)
@@ -1538,7 +1538,7 @@ static struct sample_expr *srv_sni_sample_parse_expr(struct server *srv, struct
        idx = 0;
        px->conf.args.ctx = ARGC_SRV;
 
-       return sample_parse_expr((char **)args, &idx, file, linenum, err, &px->conf.args);
+       return sample_parse_expr((char **)args, &idx, file, linenum, err, &px->conf.args, NULL);
 }
 
 static int server_parse_sni_expr(struct server *newsrv, struct proxy *px, char **err)
index 1e7d4f3a865d50806bef1d5bf5f4fef54a372979..9937f115f08e74d0d3cadb6edaefbf54c25cd2f6 100644 (file)
@@ -2118,7 +2118,7 @@ static enum act_parse_ret parse_set_gpt0(const char **args, int *arg, struct pro
        rule->arg.gpt.value = strtol(args[*arg], &error, 10);
        if (*error != '\0') {
                rule->arg.gpt.expr = sample_parse_expr((char **)args, arg, px->conf.args.file,
-                                                      px->conf.args.line, err, &px->conf.args);
+                                                      px->conf.args.line, err, &px->conf.args, NULL);
                if (!rule->arg.gpt.expr)
                        return ACT_RET_PRS_ERR;
 
index 7eb5659140c17f3e870ec8bc5b0869046139e283..fc8b4aed9245d42c184214a18da0ef51e6d3b211 100644 (file)
@@ -766,7 +766,7 @@ static int tcp_parse_request_rule(char **args, int arg, int section_type,
                arg++;
 
                curpx->conf.args.ctx = ARGC_CAP;
-               expr = sample_parse_expr(args, &arg, file, line, err, &curpx->conf.args);
+               expr = sample_parse_expr(args, &arg, file, line, err, &curpx->conf.args, NULL);
                if (!expr) {
                        memprintf(err,
                                  "'%s %s %s' : %s",
@@ -847,7 +847,7 @@ static int tcp_parse_request_rule(char **args, int arg, int section_type,
                }
 
                curpx->conf.args.ctx = ARGC_TRK;
-               expr = sample_parse_expr(args, &arg, file, line, err, &curpx->conf.args);
+               expr = sample_parse_expr(args, &arg, file, line, err, &curpx->conf.args, NULL);
                if (!expr) {
                        memprintf(err,
                                  "'%s %s %s' : %s",
index ff6baf5dcb572ec505277efa112c029d30e40339..63e2103311d5a2fe9c2242df122cc791e6416978 100644 (file)
@@ -749,7 +749,7 @@ static enum act_parse_ret parse_store(const char **args, int *arg, struct proxy
        kw_name = args[*arg-1];
 
        rule->arg.vars.expr = sample_parse_expr((char **)args, arg, px->conf.args.file,
-                                               px->conf.args.line, err, &px->conf.args);
+                                               px->conf.args.line, err, &px->conf.args, NULL);
        if (!rule->arg.vars.expr)
                return ACT_RET_PRS_ERR;