MEDIUM: vars: make var_clear() only reset VF_PERMANENT variables
We certainly do not want that a permanent variable (one that is listed
in the configuration) be erased by accident by an "unset-var" action.
Let's make sure these ones are only reset to an empty sample, like at
the moment of their initial registration. One trick is that the same
function is used to purge the memory at the end and to delete, so we
need to add an extra "force" argument to make the choice.
diff --git a/include/haproxy/vars.h b/include/haproxy/vars.h
index a40dce0..bc27e37 100644
--- a/include/haproxy/vars.h
+++ b/include/haproxy/vars.h
@@ -31,7 +31,7 @@
void vars_init_head(struct vars *vars, enum vars_scope scope);
void var_accounting_diff(struct vars *vars, struct session *sess, struct stream *strm, int size);
-unsigned int var_clear(struct var *var);
+unsigned int var_clear(struct var *var, int force);
void vars_prune(struct vars *vars, struct session *sess, struct stream *strm);
void vars_prune_per_sess(struct vars *vars);
int vars_get_by_name(const char *name, size_t len, struct sample *smp, const struct buffer *def);
diff --git a/src/vars.c b/src/vars.c
index 30aff97..6fc58dd 100644
--- a/src/vars.c
+++ b/src/vars.c
@@ -142,8 +142,11 @@
return 1;
}
-/* This fnuction remove a variable from the list and free memory it used */
-unsigned int var_clear(struct var *var)
+/* This function removes a variable from the list and frees the memory it was
+ * using. If the variable is marked "VF_PERMANENT", the sample_data is only
+ * reset to SMP_T_ANY unless <force> is non nul. Returns the freed size.
+ */
+unsigned int var_clear(struct var *var, int force)
{
unsigned int size = 0;
@@ -155,9 +158,14 @@
ha_free(&var->data.u.meth.str.area);
size += var->data.u.meth.str.data;
}
+ /* wipe the sample */
+ var->data.type = SMP_T_ANY;
+
+ if (!(var->flags & VF_PERMANENT) || force) {
+ LIST_DELETE(&var->l);
+ pool_free(var_pool, var);
+ size += sizeof(struct var);
+ }
- LIST_DELETE(&var->l);
- pool_free(var_pool, var);
- size += sizeof(struct var);
return size;
}
@@ -171,7 +179,7 @@
HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
list_for_each_entry_safe(var, tmp, &vars->head, l) {
- size += var_clear(var);
+ size += var_clear(var, 1);
}
HA_RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
var_accounting_diff(vars, sess, strm, -size);
@@ -187,7 +195,7 @@
HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
list_for_each_entry_safe(var, tmp, &vars->head, l) {
- size += var_clear(var);
+ size += var_clear(var, 1);
}
HA_RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);
@@ -494,7 +502,7 @@
HA_RWLOCK_WRLOCK(VARS_LOCK, &vars->rwlock);
var = var_get(vars, name);
if (var) {
- size = var_clear(var);
+ size = var_clear(var, 0);
var_accounting_diff(vars, smp->sess, smp->strm, -size);
}
HA_RWLOCK_WRUNLOCK(VARS_LOCK, &vars->rwlock);