From: Willy Tarreau Date: Fri, 19 Oct 2012 17:49:09 +0000 (+0200) Subject: MEDIUM: sample: pass an empty list instead of a null for fetch args X-Git-Tag: v1.5-dev13~133 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2e845be2492852b69b581c2fd11147633087ddab;p=thirdparty%2Fhaproxy.git MEDIUM: sample: pass an empty list instead of a null for fetch args ACL and sample fetches use args list and it is really not convenient to check for null args everywhere. Now for empty args we pass a constant list of end of lists. It will allow us to remove many useless checks. --- diff --git a/include/proto/arg.h b/include/proto/arg.h index 68eb379db9..8e0a81b075 100644 --- a/include/proto/arg.h +++ b/include/proto/arg.h @@ -54,6 +54,11 @@ #define ARG7(m, t1, t2, t3, t4, t5, t6, t7) \ (ARG6(m, t1, t2, t3, t4, t5, t6) + (ARGT_##t7 << 28)) +/* This dummy arg list may be used by default when no arg is found, it helps + * parsers by removing pointer checks. + */ +extern struct arg empty_arg_list[8]; + int make_arg_list(const char *in, int len, unsigned int mask, struct arg **argp, char **err_msg, const char **err_ptr, int *err_arg); diff --git a/src/acl.c b/src/acl.c index ba7c1f0ea1..f220394d96 100644 --- a/src/acl.c +++ b/src/acl.c @@ -1224,7 +1224,8 @@ static struct acl_expr *prune_acl_expr(struct acl_expr *expr) arg++; } - free(expr->args); + if (expr->args != empty_arg_list) + free(expr->args); expr->kw->use_cnt--; return expr; } @@ -1352,6 +1353,7 @@ struct acl_expr *parse_acl_expr(const char **args, char **err) aclkw->use_cnt++; LIST_INIT(&expr->patterns); expr->pattern_tree = EB_ROOT_UNIQUE; + expr->args = empty_arg_list; arg = strchr(args[0], '('); if (aclkw->arg_mask) { @@ -1380,6 +1382,9 @@ struct acl_expr *parse_acl_expr(const char **args, char **err) goto out_free_expr; } + if (!expr->args) + expr->args = empty_arg_list; + if (aclkw->val_args && !aclkw->val_args(expr->args, err)) { /* invalid keyword argument, error must have been * set by val_args(). @@ -2030,10 +2035,8 @@ acl_find_targets(struct proxy *p) list_for_each_entry(acl, &p->acl, list) { list_for_each_entry(expr, &acl->expr, list) { - for (arg = expr->args; arg; arg++) { - if (arg->type == ARGT_STOP) - break; - else if (!arg->unresolved) + for (arg = expr->args; arg && arg->type != ARGT_STOP; arg++) { + if (!arg->unresolved) continue; else if (arg->type == ARGT_SRV) { struct proxy *px; diff --git a/src/arg.c b/src/arg.c index 187540d53e..f113ba3033 100644 --- a/src/arg.c +++ b/src/arg.c @@ -36,6 +36,11 @@ static const char *arg_type_names[ARGT_NBTYPES] = { /* Unassigned types must never happen. Better crash during parsing if they do. */ }; +/* This dummy arg list may be used by default when no arg is found, it helps + * parsers by removing pointer checks. + */ +struct arg empty_arg_list[8] = { }; + /* This function builds an argument list from a config line. It returns the * number of arguments found, or <0 in case of any error. Everything needed * it automatically allocated. A pointer to an error message might be returned diff --git a/src/haproxy.c b/src/haproxy.c index 6c80f6b10c..f296f716f4 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -73,6 +73,7 @@ #include #include +#include #include #include #include @@ -818,7 +819,8 @@ static void deinit_sample_arg(struct arg *p) p++; } - free(p_back); + if (p_back != empty_arg_list) + free(p_back); } static void deinit_stick_rules(struct list *rules) diff --git a/src/sample.c b/src/sample.c index 3e0c96501a..3eef4c3342 100644 --- a/src/sample.c +++ b/src/sample.c @@ -320,6 +320,7 @@ struct sample_expr *sample_parse_expr(char **str, int *idx, char *err, int err_s LIST_INIT(&(expr->conv_exprs)); expr->fetch = fetch; + expr->arg_p = empty_arg_list; if (end != endw) { char *err_msg = NULL; @@ -344,6 +345,9 @@ struct sample_expr *sample_parse_expr(char **str, int *idx, char *err, int err_s goto out_error; } + if (!expr->arg_p) + expr->arg_p = empty_arg_list; + if (fetch->val_args && !fetch->val_args(expr->arg_p, &err_msg)) { p = my_strndup(str[*idx], endw - str[*idx]); if (p) { @@ -436,6 +440,9 @@ struct sample_expr *sample_parse_expr(char **str, int *idx, char *err, int err_s goto out_error; } + if (!conv_expr->arg_p) + conv_expr->arg_p = empty_arg_list; + if (conv->val_args && !conv->val_args(conv_expr->arg_p, &err_msg)) { p = my_strndup(str[*idx], endw - str[*idx]); if (p) {