Some argument validation (val_args) functions have unsafe side-effects,
introduce val_args_flags field to track which functions have
side-effects.

Keep the actual values in preprocessor symbols so that they can be kept
with the functions, and consumed via macros in the static lists.

Initial-Discovery: Yue Zhu <y...@digitalocean.com>
Signed-off-by: Robin H. Johnson <robb...@gentoo.org>
Signed-off-by: Robin H. Johnson <rjohn...@digitalocean.com>
---
 include/types/sample.h | 22 ++++++++++++++++++++--
 src/51d.c              |  2 ++
 src/hlua.c             |  3 +++
 src/map.c              |  1 +
 src/payload.c          |  2 ++
 src/proto_http.c       |  1 +
 src/sample.c           |  7 +++++++
 src/vars.c             |  2 ++
 8 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/include/types/sample.h b/include/types/sample.h
index a0a440512..0f4e93c30 100644
--- a/include/types/sample.h
+++ b/include/types/sample.h
@@ -206,6 +206,18 @@ enum {
        SMP_F_CONST      = 1 << 7, /* This sample use constant memory. May 
diplicate it before changes */
 };
 
+/* Flags used to describe val_args functions.
+ * In future, some of these conditions might be permitted, but for now they are
+ * only markers about types of unsafe functions.
+ */
+enum {
+       SMP_VAL_ARGS_F_SAFE         = 0,        /* no side-effects! */
+       SMP_VAL_ARGS_F_UNSAFE_VAR   = 1 << 0,   /* unsafe side-effect: creates 
variable */
+       SMP_VAL_ARGS_F_UNSAFE_ALLOC = 1 << 1,   /* unsafe side-effect: 
allocates */
+       SMP_VAL_ARGS_F_UNSAFE_FILE  = 1 << 2,   /* unsafe side-effect: file 
access */
+       SMP_VAL_ARGS_F_UNSAFE_ANY   = (1<<0)|(1<<1)|(1<<2), /* any unsafe 
side-effect */
+};
+
 /* needed below */
 struct session;
 struct stream;
@@ -291,6 +303,7 @@ struct sample_conv {
                        struct sample_conv *smp_conv,
                        const char *file, int line,
                        char **err_msg);          /* argument validation 
function */
+       unsigned int val_args_flags;              /* argument validation flags 
*/
        unsigned int in_type;                     /* expected input sample type 
*/
        unsigned int out_type;                    /* output sample type */
        void *private;                            /* private values. only used 
by maps and Lua */
@@ -313,6 +326,7 @@ struct sample_fetch {
        uint64_t arg_mask;                        /* arguments (ARG*()) */
        int (*val_args)(struct arg *arg_p,
                        char **err_msg);          /* argument validation 
function */
+       unsigned int val_args_flags;              /* argument validation flags 
*/
        unsigned long out_type;                   /* output sample type */
        unsigned int use;                         /* fetch source (SMP_USE_*) */
        unsigned int val;                         /* fetch validity (SMP_VAL_*) 
*/
@@ -344,8 +358,12 @@ extern sample_cast_fct sample_casts[SMP_TYPES][SMP_TYPES];
 
 /* Macros for easier to use val_args list usage
  * All sample_conv_kw_list/sample_fetch_kw_list should use the SMP_VAL_ARGS 
macro to populate the
- * val_args field.
+ * val_args and val_args_flags fields together.
+ * They should define SMP_VAL_ARGS_SAFEVAL_funcname as the bitfield of 
SMP_VAL_ARGS_F_* enum.
+ * SMP_VAL_ARGS(NULL) is common for fetches with no arguments or no validation
  */
-#define SMP_VAL_ARGS(func)        func
+#define SMP_VAL_ARGS(func)        func, SMP_VAL_ARGS_SAFEVAL_##func
+#define SMP_VAL_ARGS_SAFEVAL(x)   SMP_VAL_ARGS_SAFEVAL_##x
+#define SMP_VAL_ARGS_SAFEVAL_NULL SMP_VAL_ARGS_F_SAFE
 
 #endif /* _TYPES_SAMPLE_H */
diff --git a/src/51d.c b/src/51d.c
index f415fac26..d6e130e82 100644
--- a/src/51d.c
+++ b/src/51d.c
@@ -133,6 +133,7 @@ static int _51d_cache_size(char **args, int section_type, 
struct proxy *curpx,
        return 0;
 }
 
+#define SMP_VAL_ARGS_SAFEVAL__51d_fetch_check SMP_VAL_ARGS_F_SAFE
 static int _51d_fetch_check(struct arg *arg, char **err_msg)
 {
        if (global_51degrees.data_file_path)
@@ -142,6 +143,7 @@ static int _51d_fetch_check(struct arg *arg, char **err_msg)
        return 0;
 }
 
+#define SMP_VAL_ARGS_SAFEVAL__51d_conv_check SMP_VAL_ARGS_F_SAFE
 static int _51d_conv_check(struct arg *arg, struct sample_conv *conv,
                            const char *file, int line, char **err_msg)
 {
diff --git a/src/hlua.c b/src/hlua.c
index 085544dc6..a9d126b53 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -1471,6 +1471,7 @@ __LJMP static int hlua_map_new(struct lua_State *L)
        conv.process = NULL; /* unused. */
        conv.arg_mask = 0; /* unused. */
        conv.val_args = NULL; /* unused. */
+       conv.val_args_flags = SMP_VAL_ARGS_SAFEVAL(NULL); /* unused */
        conv.out_type = SMP_T_STR;
        conv.private = (void *)(long)match;
        switch (match) {
@@ -6011,6 +6012,7 @@ __LJMP static int hlua_register_converters(lua_State *L)
        sck->kw[0].process = hlua_sample_conv_wrapper;
        sck->kw[0].arg_mask = 
ARG12(0,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR);
        sck->kw[0].val_args = NULL;
+       sck->kw[0].val_args_flags = SMP_VAL_ARGS_SAFEVAL(NULL);
        sck->kw[0].in_type = SMP_T_STR;
        sck->kw[0].out_type = SMP_T_STR;
        sck->kw[0].private = fcn;
@@ -6068,6 +6070,7 @@ __LJMP static int hlua_register_fetches(lua_State *L)
        sfk->kw[0].process = hlua_sample_fetch_wrapper;
        sfk->kw[0].arg_mask = 
ARG12(0,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR,STR);
        sfk->kw[0].val_args = NULL;
+       sfk->kw[0].val_args_flags = SMP_VAL_ARGS_SAFEVAL(NULL);
        sfk->kw[0].out_type = SMP_T_STR;
        sfk->kw[0].use = SMP_USE_HTTP_ANY;
        sfk->kw[0].val = 0;
diff --git a/src/map.c b/src/map.c
index 0b86e809c..e70c94a90 100644
--- a/src/map.c
+++ b/src/map.c
@@ -99,6 +99,7 @@ static struct map_descriptor *map_create_descriptor(struct 
sample_conv *conv)
  * This function choose the indexation type (ebtree or list) according with
  * the type of match needed.
  */
+#define SMP_VAL_ARGS_SAFEVAL_sample_load_map   
(SMP_VAL_ARGS_F_UNSAFE_FILE|SMP_VAL_ARGS_F_UNSAFE_ALLOC)
 int sample_load_map(struct arg *arg, struct sample_conv *conv,
                     const char *file, int line, char **err)
 {
diff --git a/src/payload.c b/src/payload.c
index 9416fa6ef..439c771dd 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -875,6 +875,7 @@ smp_fetch_payload(const struct arg *arg_p, struct sample 
*smp, const char *kw, v
  * The value is contained in the 63 MSB and the LSB is used as a flag for 
marking
  * the "relative" property of the value.
  */
+#define SMP_VAL_ARGS_SAFEVAL_val_payload_lv SMP_VAL_ARGS_F_SAFE
 int val_payload_lv(struct arg *arg, char **err_msg)
 {
        int relative = 0;
@@ -1083,6 +1084,7 @@ smp_fetch_distcc_body(const struct arg *arg_p, struct 
sample *smp, const char *k
  * error message in case of error, that the caller is responsible for freeing.
  * The initial location must either be freeable or NULL.
  */
+#define SMP_VAL_ARGS_SAFEVAL_val_distcc SMP_VAL_ARGS_F_SAFE
 int val_distcc(struct arg *arg, char **err_msg)
 {
        unsigned int token;
diff --git a/src/proto_http.c b/src/proto_http.c
index 0136f505b..dabb40100 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -11506,6 +11506,7 @@ smp_fetch_url32_src(const struct arg *args, struct 
sample *smp, const char *kw,
  * error message in case of error, that the caller is responsible for freeing.
  * The initial location must either be freeable or NULL.
  */
+#define SMP_VAL_ARGS_SAFEVAL_val_hdr SMP_VAL_ARGS_F_SAFE
 int val_hdr(struct arg *arg, char **err_msg)
 {
        if (arg && arg[1].type == ARGT_SINT && arg[1].data.sint < 
-MAX_HDR_HISTORY) {
diff --git a/src/sample.c b/src/sample.c
index b4ed77d48..93db71aa1 100644
--- a/src/sample.c
+++ b/src/sample.c
@@ -1736,6 +1736,7 @@ enum input_type {
        IT_UTF8P,
        IT_UTF8PS,
 };
+#define SMP_VAL_ARGS_SAFEVAL_sample_conv_json_check SMP_VAL_ARGS_F_SAFE
 static int sample_conv_json_check(struct arg *arg, struct sample_conv *conv,
                                   const char *file, int line, char **err)
 {
@@ -1922,6 +1923,7 @@ static int sample_conv_bytes(const struct arg *arg_p, 
struct sample *smp, void *
        return 1;
 }
 
+#define SMP_VAL_ARGS_SAFEVAL_sample_conv_field_check SMP_VAL_ARGS_F_SAFE
 static int sample_conv_field_check(struct arg *args, struct sample_conv *conv,
                                   const char *file, int line, char **err)
 {
@@ -2069,6 +2071,7 @@ found:
        return 1;
 }
 
+#define SMP_VAL_ARGS_SAFEVAL_sample_conv_regsub_check SMP_VAL_ARGS_F_SAFE
 static int sample_conv_regsub_check(struct arg *args, struct sample_conv *conv,
                                     const char *file, int line, char **err)
 {
@@ -2178,6 +2181,7 @@ static int sample_conv_regsub(const struct arg *arg_p, 
struct sample *smp, void
 /* This function check an operator entry. It expects a string.
  * The string can be an integer or a variable name.
  */
+#define SMP_VAL_ARGS_SAFEVAL_check_operator SMP_VAL_ARGS_F_UNSAFE_VAR
 static int check_operator(struct arg *args, struct sample_conv *conv,
                           const char *file, int line, char **err)
 {
@@ -2639,6 +2643,7 @@ static int smp_fetch_const_str(const struct arg *args, 
struct sample *smp, const
        return 1;
 }
 
+#define SMP_VAL_ARGS_SAFEVAL_smp_check_const_bool SMP_VAL_ARGS_F_SAFE
 static int smp_check_const_bool(struct arg *args, char **err)
 {
        if (strcasecmp(args[0].data.str.str, "true") == 0 ||
@@ -2685,6 +2690,7 @@ static int smp_fetch_const_ipv6(const struct arg *args, 
struct sample *smp, cons
        return 1;
 }
 
+#define SMP_VAL_ARGS_SAFEVAL_smp_check_const_bin SMP_VAL_ARGS_F_UNSAFE_ALLOC
 static int smp_check_const_bin(struct arg *args, char **err)
 {
        char *binstr = NULL;
@@ -2707,6 +2713,7 @@ static int smp_fetch_const_bin(const struct arg *args, 
struct sample *smp, const
        return 1;
 }
 
+#define SMP_VAL_ARGS_SAFEVAL_smp_check_const_meth SMP_VAL_ARGS_F_SAFE
 static int smp_check_const_meth(struct arg *args, char **err)
 {
        enum http_meth_t meth;
diff --git a/src/vars.c b/src/vars.c
index fab83c5d2..996d6e6e4 100644
--- a/src/vars.c
+++ b/src/vars.c
@@ -697,11 +697,13 @@ static enum act_return action_clear(struct act_rule 
*rule, struct proxy *px,
  * The first function checks a sample-fetch and the second
  * checks a converter.
  */
+#define SMP_VAL_ARGS_SAFEVAL_smp_check_var SMP_VAL_ARGS_F_UNSAFE_VAR
 static int smp_check_var(struct arg *args, char **err)
 {
        return vars_check_arg(&args[0], err);
 }
 
+#define SMP_VAL_ARGS_SAFEVAL_conv_check_var SMP_VAL_ARGS_F_UNSAFE_VAR
 static int conv_check_var(struct arg *args, struct sample_conv *conv,
                           const char *file, int line, char **err_msg)
 {
-- 
2.18.0


Reply via email to