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/src/acl.c b/src/acl.c
index ba7c1f0..f220394 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -1224,7 +1224,8 @@
arg++;
}
- free(expr->args);
+ if (expr->args != empty_arg_list)
+ free(expr->args);
expr->kw->use_cnt--;
return expr;
}
@@ -1352,6 +1353,7 @@
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 @@
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 @@
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 187540d..f113ba3 100644
--- a/src/arg.c
+++ b/src/arg.c
@@ -36,6 +36,11 @@
/* 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 6c80f6b..f296f71 100644
--- a/src/haproxy.c
+++ b/src/haproxy.c
@@ -73,6 +73,7 @@
#include <proto/auth.h>
#include <proto/acl.h>
+#include <proto/arg.h>
#include <proto/backend.h>
#include <proto/channel.h>
#include <proto/checks.h>
@@ -818,7 +819,8 @@
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 3e0c965..3eef4c3 100644
--- a/src/sample.c
+++ b/src/sample.c
@@ -320,6 +320,7 @@
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 @@
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 @@
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) {