]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: vars: make var_clear() only reset VF_PERMANENT variables
authorWilly Tarreau <w@1wt.eu>
Wed, 8 Sep 2021 13:03:58 +0000 (15:03 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 8 Sep 2021 13:06:11 +0000 (15:06 +0200)
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.

include/haproxy/vars.h
src/vars.c

index a40dce028b3cf79bf7791333a8c3b1c804d0f0f2..bc27e37989e378377c3ad12aab84a52de373786e 100644 (file)
@@ -31,7 +31,7 @@ extern struct vars proc_vars;
 
 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);
index 30aff97e8aa4a7157bc5f5bbd06d1f4551a7bef2..6fc58dd33b2cfcf14ce8d086b10d4cd6909de0fd 100644 (file)
@@ -142,8 +142,11 @@ scope_sess:
        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 @@ unsigned int var_clear(struct var *var)
                ha_free(&var->data.u.meth.str.area);
                size += var->data.u.meth.str.data;
        }
-       LIST_DELETE(&var->l);
-       pool_free(var_pool, var);
-       size += sizeof(struct var);
+       /* 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);
+       }
        return size;
 }
 
@@ -171,7 +179,7 @@ void vars_prune(struct vars *vars, struct session *sess, struct stream *strm)
 
        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 @@ void vars_prune_per_sess(struct vars *vars)
 
        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 @@ static int var_unset(const char *name, enum vars_scope scope, struct sample *smp
        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);