From: Aurelien DARRAGON Date: Tue, 6 Jun 2023 17:03:45 +0000 (+0200) Subject: MINOR: sample: introduce c_pseudo() conv function X-Git-Tag: v2.9-dev2~84 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=30cd137d3f19076640523164a6c11058795eb47d;p=thirdparty%2Fhaproxy.git MINOR: sample: introduce c_pseudo() conv function This function is used for ANY=>!ANY conversions in the compatibility matrix to help differentiate between real NOOP (c_none) and pseudo conversions that are theorically supported at config parse time but can never occur at runtime,. That is, to explicit the fact that actual related runtime operations (e.g.: ANY->IPV4) are not NOOP since they might require some conversion to be performed depending on the input type. When checking the conf we don't know the effective out types so cast[pseudo type][pseudo type] is allowed in the compatibility matrix, but at runtime we only expect cast[real type][(real type || pseudo type)] because fetches and converters may not emit pseudo types, thus using c_none() everywhere was too ambiguous. The process will crash if c_pseudo() is invoked to help catch bugs: crashing here means that a pseudo type has been encountered on a converter's input at runtime (because it was emitted earlier in the chain), which is not supported and results from a broken sample fetch or converter implementation. (pseudo types may only be used as out_type in sample definitions for compatibility checks at parsing time) --- diff --git a/include/haproxy/sample-t.h b/include/haproxy/sample-t.h index 7fb9f5e9b2..9969a18d6c 100644 --- a/include/haproxy/sample-t.h +++ b/include/haproxy/sample-t.h @@ -26,9 +26,14 @@ #include #include -/* input and output sample types */ +/* input and output sample types + * + * Some of them are pseudo types which means that they can be used for + * in_type and out_type in sample (fetches/conv) definitions (they serve as + * compatibility and conversion hints) but they cannot be emitted at runtime. + */ enum { - SMP_T_ANY = 0, /* any type */ + SMP_T_ANY = 0, /* pseudo type: any type */ SMP_T_BOOL, /* boolean */ SMP_T_SINT, /* signed 64bits integer type */ SMP_T_ADDR, /* ipv4 or ipv6, only used for input type compatibility */ diff --git a/include/haproxy/sample.h b/include/haproxy/sample.h index 74c206b255..a941a65de2 100644 --- a/include/haproxy/sample.h +++ b/include/haproxy/sample.h @@ -59,6 +59,7 @@ int smp_resolve_args(struct proxy *p, char **err); int smp_check_date_unit(struct arg *args, char **err); int smp_expr_output_type(struct sample_expr *expr); int c_none(struct sample *smp); +int c_pseudo(struct sample *smp); int smp_dup(struct sample *smp); /* diff --git a/src/sample.c b/src/sample.c index d496ddbd94..a8eb50713d 100644 --- a/src/sample.c +++ b/src/sample.c @@ -864,6 +864,22 @@ int c_none(struct sample *smp) return 1; } +/* special converter function used by pseudo types in the compatibility matrix + * to inform that the conversion is theorically allowed at parsing time. + * + * However, being a pseudo type, it may not be emitted by fetches or converters + * so this function should never be called. If this is the case, then it means + * that a pseudo type has been used as a final output type at runtime, which is + * considered as a bug and should be fixed. To help spot this kind of bug, the + * process will crash in this case. + */ +int c_pseudo(struct sample *smp) +{ + ABORT_NOW(); // die loudly + /* never reached */ + return 0; +} + static int c_str2int(struct sample *smp) { const char *str; @@ -978,7 +994,7 @@ static int c_bool2bin(struct sample *smp) sample_cast_fct sample_casts[SMP_TYPES][SMP_TYPES] = { /* to: ANY BOOL SINT ADDR IPV4 IPV6 STR BIN METH */ -/* from: ANY */ { c_none, c_none, c_none, c_none, c_none, c_none, c_none, c_none, c_none, }, +/* from: ANY */ { c_none, c_pseudo, c_pseudo, c_pseudo, c_pseudo, c_pseudo, c_pseudo, c_pseudo, c_pseudo, }, /* BOOL */ { c_none, c_none, c_none, NULL, NULL, NULL, c_int2str, c_bool2bin, NULL, }, /* SINT */ { c_none, c_none, c_none, c_int2ip, c_int2ip, c_int2ipv6, c_int2str, c_int2bin, NULL, }, /* ADDR */ { c_none, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, },