xlat_escape_legacy_t escape, void const *escape_ctx,
fr_type_t dst_type)
{
- fr_value_box_t const *to_cast = NULL;
+ fr_value_box_t *to_cast = NULL;
fr_value_box_t from_cast;
fr_pair_t *vp = NULL;
{
RDEBUG4("EXPAND TMPL DATA");
- to_cast = tmpl_value(vpt);
+ to_cast = UNCONST(fr_value_box_t *, tmpl_value(vpt));
switch (to_cast->type) {
case FR_TYPE_STRING:
case FR_TYPE_OCTETS:
uint8_t *bin;
size_t len, outlen;
fr_sbuff_parse_error_t err;
- fr_value_box_t *in_head;
+ fr_value_box_t *hex;
- in_head = fr_dlist_head(in);
- len = in_head->vb_length;
+ hex = fr_dlist_head(in);
+ len = hex->vb_length;
if ((len > 1) && (len & 0x01)) {
REDEBUG("Input data length must be >1 and even, got %zu", len);
return XLAT_ACTION_FAIL;
}
- p = in_head->vb_strvalue;
+ p = hex->vb_strvalue;
end = p + len;
/*
*
* @ingroup xlat_functions
*/
-static xlat_action_t xlat_func_hex(TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED request_t *request,
+static xlat_action_t xlat_func_hex(UNUSED TALLOC_CTX *ctx, fr_dcursor_t *out, UNUSED request_t *request,
UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst,
fr_value_box_list_t *in)
{
- char *p;
- fr_value_box_t* vb;
- fr_value_box_t* in_head;
-
- in_head = fr_dlist_head(in);
+ char *new_buff;
+ fr_value_box_t *bin = fr_dlist_pop_head(in); /* First argument */
- MEM(vb = fr_value_box_alloc(ctx, FR_TYPE_STRING, NULL, false));
- vb->vb_length = (in_head->vb_length * 2);
- vb->vb_strvalue = p = talloc_zero_array(vb, char, vb->vb_length + 1);
- if (in_head->vb_length) {
- fr_bin2hex(&FR_SBUFF_OUT(p, talloc_array_length(p)), &FR_DBUFF_TMP(in_head->vb_octets, in_head->vb_length), SIZE_MAX);
+ /*
+ * Use existing box, but with new buffer
+ */
+ MEM(new_buff = talloc_zero_array(bin, char, (bin->vb_length * 2) + 1));
+ if (bin->vb_length) {
+ fr_bin2hex(&FR_SBUFF_OUT(new_buff, (bin->vb_length * 2) + 1),
+ &FR_DBUFF_TMP(bin->vb_octets, bin->vb_length), SIZE_MAX);
+ fr_value_box_clear_value(bin);
+ fr_value_box_strdup_shallow(bin, NULL, new_buff, bin->tainted);
+ /*
+ * Zero length binary > zero length hex string
+ */
+ } else {
+ fr_value_box_clear_value(bin);
+ fr_value_box_strdup(bin, bin, NULL, "", bin->tainted);
}
-
- fr_dcursor_append(out, vb);
+ fr_dcursor_append(out, bin);
return XLAT_ACTION_DONE;
}
xlat_thread_inst_t *thread_inst;
fr_value_box_list_t result_copy;
- fr_value_box_list_init(&result_copy);
thread_inst = xlat_thread_instance_find(node);
XLAT_DEBUG("** [%i] %s(func-async) - %%{%s:%pM}",
unlang_interpret_stack_depth(request), __FUNCTION__,
node->fmt, result);
+ VALUE_BOX_LIST_VERIFY(result);
/*
* Need to copy the input list in case
* the async function mucks with it.
*/
- if (RDEBUG_ENABLED2) fr_value_box_list_acopy(NULL, &result_copy, result);
-
- VALUE_BOX_LIST_VERIFY(result);
+ if (RDEBUG_ENABLED2) {
+ fr_value_box_list_init(&result_copy);
+ fr_value_box_list_acopy(NULL, &result_copy, result);
+ }
xa = xlat_process_args(ctx, result, request, node->call.func->input_type, node->call.func->args);
if (xa == XLAT_ACTION_FAIL) {
if (RDEBUG_ENABLED2) fr_dlist_talloc_free(&result_copy);
return xa;
}
+ VALUE_BOX_LIST_VERIFY(result);
xa = node->call.func->func.async(ctx, out, request,
node->call.inst->data, thread_inst->data, result);
xlat_debug_log_expansion(request, *in, NULL);
xlat_debug_log_result(request, value);
+ VALUE_BOX_VERIFY(value);
+
fr_dcursor_insert(out, value);
}
break;
for (node = *in; node; node = (*in)->next) {
*in = node; /* Update node in our caller */
fr_dcursor_tail(out); /* Needed for debugging */
+ VALUE_BOX_LIST_VERIFY(out->dlist);
switch (node->type) {
case XLAT_LITERAL:
}
finish:
+ VALUE_BOX_LIST_VERIFY(out->dlist);
XLAT_DEBUG("** [%i] %s << %s", unlang_interpret_stack_depth(request),
__FUNCTION__, fr_table_str_by_value(xlat_action_table, xa, "<INVALID>"));
* Does nothing if the list was not initialised with #fr_dlist_talloc_init.
*/
#ifndef TALLOC_GET_TYPE_ABORT_NOOP
-static inline CC_HINT(nonnull) void fr_dlist_verify(char const *file, int line, fr_dlist_head_t *list_head)
+static inline CC_HINT(nonnull) void fr_dlist_verify(char const *file, int line, fr_dlist_head_t const *list_head)
{
void *item;
case FR_TYPE_VARIABLE_SIZE:
dst->vb_length = src->vb_length;
break;
+ /*
+ * Not 100% sure this should be done here
+ * but if the intent is to make a null
+ * box usable, then we need to do this
+ * somewhere.
+ */
+ case FR_TYPE_GROUP:
+ fr_value_box_list_init(&dst->vb_group);
+ break;
default:
break;
talloc_free(data->datum.ptr);
break;
- case FR_TYPE_STRUCTURAL:
+ case FR_TYPE_GROUP:
/*
* Depth first freeing of children
*
{
fr_value_box_t *vb = NULL;
- while ((vb = fr_dlist_next(&data->datum.children, vb))) {
+ while ((vb = fr_dlist_next(&data->vb_group, vb))) {
fr_value_box_clear_value(vb);
talloc_free(vb);
}
memcpy(((uint8_t *)dst) + fr_value_box_offsets[src->type],
((uint8_t const *)src) + fr_value_box_offsets[src->type],
fr_value_box_field_sizes[src->type]);
+ fr_value_box_copy_meta(dst, src);
break;
case FR_TYPE_STRING:
return -1;
}
dst->vb_strvalue = str;
+ fr_value_box_copy_meta(dst, src);
}
break;
talloc_set_type(bin, uint8_t);
}
dst->vb_octets = bin;
+ fr_value_box_copy_meta(dst, src);
}
break;
- }
- fr_value_box_copy_meta(dst, src);
+ case FR_TYPE_GROUP:
+ {
+ fr_value_box_t *child;
+
+ fr_value_box_copy_meta(dst, src); /* Initialises group child dlist */
+
+ while ((child = fr_dlist_next(&src->vb_group, child))) {
+ fr_value_box_t *new;
+
+ /*
+ * Build out the child
+ */
+ new = fr_value_box_alloc_null(ctx);
+ if (unlikely(!new)) {
+ group_error:
+ fr_strerror_const("Failed duplicating group child");
+ fr_dlist_talloc_free(&dst->vb_group);
+ return -1;
+ }
+
+ /*
+ * Populate it with the
+ * data from the original
+ * child.
+ */
+ if (unlikely(fr_value_box_copy(new, new, child) < 0)) goto group_error;
+ fr_dlist_insert_tail(&dst->vb_group, new);
+ }
+ }
+ break;
+ }
return 0;
}
* - 0 on success.
* - -1 on failure.
*/
-int fr_value_box_steal(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *src)
+int fr_value_box_steal(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t *src)
{
if (!fr_cond_assert(src->type != FR_TYPE_NULL)) return -1;
talloc_set_type(str, char);
dst->vb_strvalue = str;
fr_value_box_copy_meta(dst, src);
+ memset(&src->datum, 0, sizeof(src->datum));
}
return 0;
dst->vb_octets = bin;
fr_value_box_copy_meta(dst, src);
+ memset(&src->datum, 0, sizeof(src->datum));
+ }
+ return 0;
+
+ case FR_TYPE_GROUP:
+ {
+ fr_value_box_t *child;
+
+ while ((child = fr_dlist_pop_head(&src->vb_group))) {
+ child = talloc_steal(ctx, child);
+ if (unlikely(!child)) {
+ fr_strerror_const("Failed stealing child");
+ return -1;
+ }
+ fr_dlist_insert_tail(&dst->vb_group, child);
+ }
}
return 0;
}
void value_box_list_verify(char const *file, int line, fr_value_box_list_t const *list)
{
- fr_value_box_t const *vb;
+ fr_value_box_t const *vb = NULL;
FR_DLIST_VERIFY(list);
- while ((vb = fr_dlist_next(list, vb))) value_box_verify(file, line, list);
+ while ((vb = fr_dlist_next(list, vb))) value_box_verify(file, line, vb);
}
*/
static inline void fr_value_box_list_init(fr_value_box_list_t *list)
{
- fr_dlist_talloc_init(list, fr_value_box_t, entry);
+ fr_dlist_init(list, fr_value_box_t, entry); /* Not always talloced */
}
/** @} */
void fr_value_box_copy_shallow(TALLOC_CTX *ctx, fr_value_box_t *dst,
const fr_value_box_t *src);
-int fr_value_box_steal(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t const *src);
+int fr_value_box_steal(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_value_box_t *src);
/** @} */
/** @name Assign and manipulate binary-unsafe C strings