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