///< tainted ones.
fr_type_t type; //!< Type to cast argument to.
xlat_escape_func_t func; //!< Function to handle tainted values.
- void *uctx; //!< Arcument to escape callback.
+ void *uctx; //!< Argument to pass to escape callback.
} xlat_arg_parser_t;
#define XLAT_ARG_PARSER_TERMINATOR { .required = false, .concat = false, .single = false, .variadic = false, \
xlat_t *xlat_register(TALLOC_CTX *ctx, char const *name, xlat_func_t func, bool needs_async) CC_HINT(nonnull(2));
-void xlat_func_args(xlat_t *xlat, xlat_arg_parser_t const args[]) CC_HINT(nonnull);
+int xlat_func_args(xlat_t *xlat, xlat_arg_parser_t const args[]) CC_HINT(nonnull);
-void xlat_func_mono(xlat_t *xlat, xlat_arg_parser_t const *arg) CC_HINT(nonnull);
+int xlat_func_mono(xlat_t *xlat, xlat_arg_parser_t const *arg) CC_HINT(nonnull);
void xlat_internal(xlat_t *xlat);
*
* @param[in] arg specification to validate.
*/
-static inline void xlat_arg_parser_validate(xlat_arg_parser_t const *arg)
+static inline int xlat_arg_parser_validate(xlat_arg_parser_t const *arg, bool last)
{
if (arg->concat) {
- fr_assert((arg->type == FR_TYPE_STRING) || (arg->type == FR_TYPE_OCTETS));
+ if (!fr_cond_assert_msg((arg->type == FR_TYPE_STRING) || (arg->type == FR_TYPE_OCTETS),
+ "concat type must be string or octets")) return -1;
+
+ if (!fr_cond_assert_msg(!arg->single, "concat and single are mutually exclusive")) return -1;
+ }
+
+ if (arg->single) {
+ if (!fr_cond_assert_msg(!arg->concat, "single and concat are mutually exclusive")) return -1;
+ }
+
+ if (arg->variadic) {
+ if (!fr_cond_assert_msg(last, "variadic can only be set on the last argument")) return -1;
+ }
+
+ if (arg->always_escape) {
+ if (!fr_cond_assert_msg(arg->func, "always_escape requires an escape func")) return -1;
+ }
+
+ if (arg->uctx) {
+ if (!fr_cond_assert_msg(arg->func, "uctx requires an escape func")) return -1;
+ }
+
+ switch (arg->type) {
+ case FR_TYPE_VALUE:
+ break;
+
+ default:
+ fr_assert_fail("type must be a leaf box type");
+ return -1;
}
+
+ return 0;
}
/** Register the arguments of an xlat
*
* @param[in,out] x to have it's arguments registered
* @param[in] args to be registered
+ * @return
+ * - 0 on success.
+ * - < 0 on failure.
*/
-void xlat_func_args(xlat_t *x, xlat_arg_parser_t const args[])
+int xlat_func_args(xlat_t *x, xlat_arg_parser_t const args[])
{
xlat_arg_parser_t const *arg = args;
- for (arg = args; arg->type != FR_TYPE_NULL; arg++) xlat_arg_parser_validate(arg);
-
+ for (arg = args; arg->type != FR_TYPE_NULL; arg++) {
+ if (xlat_arg_parser_validate(arg, (arg + 1)->type == FR_TYPE_NULL) < 0) return -1;
+ }
x->args = args;
x->input_type = XLAT_INPUT_ARGS;
+
+ return 0;
}
/** Register the argument of an xlat
*
* @param[in,out] x to have it's arguments registered
* @param[in] arg to be registered
+ * @return
+ * - 0 on success.
+ * - < 0 on failure.
*/
-void xlat_func_mono(xlat_t *x, xlat_arg_parser_t const *arg)
+int xlat_func_mono(xlat_t *x, xlat_arg_parser_t const *arg)
{
- xlat_arg_parser_validate(arg);
+ if (xlat_arg_parser_validate(arg, true) < 0) return -1;
+
x->args = arg;
x->input_type = XLAT_INPUT_MONO;
+
+ return 0;
}
/** Mark an xlat function as internal