]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: sample: introduce c_pseudo() conv function
authorAurelien DARRAGON <adarragon@haproxy.com>
Tue, 6 Jun 2023 17:03:45 +0000 (19:03 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 3 Jul 2023 14:32:01 +0000 (16:32 +0200)
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)

include/haproxy/sample-t.h
include/haproxy/sample.h
src/sample.c

index 7fb9f5e9b2d5cdd7eb0dea0bf89b6c52e4b8baf6..9969a18d6cea3bcb195696888a39e50c58147095 100644 (file)
 #include <haproxy/api-t.h>
 #include <haproxy/sample_data-t.h>
 
-/* 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 */
index 74c206b25573e4ce39ad6c3fc5c219e831e4d473..a941a65de21fca6d7af9c6810a61bcefec65897e 100644 (file)
@@ -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);
 
 /*
index d496ddbd940d6479fe830d83a012172f7faddbd5..a8eb50713d180bcf3029d7a87cc7019053f443df 100644 (file)
@@ -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,       },