]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
move eval cast code to tmpl_eval_cast
authorAlan T. DeKok <aland@freeradius.org>
Wed, 29 Jun 2022 12:38:27 +0000 (08:38 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 30 Jun 2022 11:24:31 +0000 (07:24 -0400)
and call it from tmpl_eval_pair(), so that the caller doesn't have
to.

src/lib/server/tmpl.h
src/lib/server/tmpl_eval.c
src/lib/unlang/xlat_eval.c

index 104e0c482f7c081873fd50d3915af77c128fb640..078532f5e7fbc2485c68980850af588647955c39 100644 (file)
@@ -1135,6 +1135,8 @@ int                       tmpl_extents_build_to_leaf_parent(fr_dlist_head_t *leaf, fr_dlist_head_t *
 void                   tmpl_extents_debug(fr_dlist_head_t *head) CC_HINT(nonnull);
 
 int                    tmpl_eval_pair(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request, tmpl_t const *vpt);
+
+int                    tmpl_eval_cast(TALLOC_CTX *ctx, fr_value_box_list_t *out, tmpl_t const *vpt);
 /** @} */
 
 ssize_t                        tmpl_preparse(char const **out, size_t *outlen, char const *in, size_t inlen,
index 3026a8e092ddb96f54d522ebad24bed51a882bef..5361d26432f88a5a2ade063e05041a65f082cfde 100644 (file)
@@ -1246,9 +1246,12 @@ int tmpl_eval_pair(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request
        tmpl_dcursor_ctx_t      cc;
 
        int                     ret = 0;
+       fr_value_box_list_t     list;
 
        fr_assert(tmpl_is_attr(vpt) || tmpl_is_list(vpt));
 
+       fr_value_box_list_init(&list);
+
        /*
         *      See if we're dealing with an attribute in the request
         *
@@ -1265,7 +1268,7 @@ int tmpl_eval_pair(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request
         */
        if (!vp) {
                if (tmpl_is_attr(vpt) && tmpl_da(vpt)->flags.virtual) {
-                       ret = tmpl_eval_pair_virtual(ctx, out, request, vpt);
+                       ret = tmpl_eval_pair_virtual(ctx, &list, request, vpt);
                        goto done;
                }
 
@@ -1277,11 +1280,11 @@ int tmpl_eval_pair(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request
                        if (!value) {
                        oom:
                                fr_strerror_const("Out of memory");
-                               ret = XLAT_ACTION_FAIL;
-                               goto done;
+                               ret = -1;
+                               goto fail;
                        }
                        value->datum.int32 = 0;
-                       fr_dlist_insert_tail(out, value);
+                       fr_dlist_insert_tail(&list, value);
                } /* Fall through to being done */
 
                goto done;
@@ -1301,7 +1304,7 @@ int tmpl_eval_pair(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request
 
                value = fr_value_box_alloc(ctx, FR_TYPE_UINT32, NULL, false);
                value->datum.uint32 = count;
-               fr_dlist_insert_tail(out, value);
+               fr_dlist_insert_tail(&list, value);
                break;
        }
 
@@ -1320,7 +1323,7 @@ int tmpl_eval_pair(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request
                     vp = fr_dcursor_next(&cursor)) {
                        value = fr_value_box_alloc(ctx, vp->data.type, vp->da, vp->data.tainted);
                        fr_value_box_copy(value, value, &vp->data);
-                       fr_dlist_insert_tail(out, value);
+                       fr_dlist_insert_tail(&list, value);
                }
                break;
 
@@ -1335,15 +1338,92 @@ int tmpl_eval_pair(TALLOC_CTX *ctx, fr_value_box_list_t *out, request_t *request
 
                fr_assert(fr_type_is_leaf(vp->da->type));
                fr_value_box_copy(value, value, &vp->data);     /* Also dups taint */
-               fr_dlist_insert_tail(out, value);
+               fr_dlist_insert_tail(&list, value);
                break;
        }
 
 done:
+       /*
+        *      Evaluate casts if necessary.
+        */
+       if (ret == 0) {
+               if (tmpl_eval_cast(ctx, &list, vpt) < 0) {
+                       fr_dlist_talloc_free(&list);
+                       goto fail;
+               }
+
+               fr_dlist_move(out, &list);
+       }
+
+fail:
        tmpl_dursor_clear(&cc);
        return ret;
 }
 
+/** Casts a value or list of values according to the tmpl
+ *
+ * @param[in] ctx      to allocate boxed value, and buffers in.
+ * @param[in,out] list Where to write the boxed value.
+ * @param[in] vpt      Representing the attribute.
+ * @return
+ *     - <0            the cast failed
+ *     - 0             we successfully evaluated the tmpl
+ */
+int tmpl_eval_cast(TALLOC_CTX *ctx, fr_value_box_list_t *list, tmpl_t const *vpt)
+{
+       fr_type_t cast = tmpl_rules_cast(vpt);
+       fr_value_box_t *vb;
+       bool tainted;
+       ssize_t slen, vlen;
+       fr_sbuff_t *agg;
+
+       if (cast == FR_TYPE_NULL) return 0;
+
+       /*
+        *      Apply a cast to the results if required.
+        */
+       vb = fr_dlist_head(list);
+
+       switch (cast) {
+       default:
+               /*
+                *      One box, we cast it as the destination type.
+                *
+                *      Many boxes, turn them into strings, and try to parse it as the
+                *      output type.
+                */
+               if (!fr_dlist_next(list, vb)) {
+                       return fr_value_box_cast_in_place(vb, vb, cast, NULL);
+               }
+
+               FR_SBUFF_TALLOC_THREAD_LOCAL(&agg, 256, 256);
+
+               slen = fr_value_box_list_concat_as_string(&tainted, agg, list, NULL, 0, NULL,
+                                                         FR_VALUE_BOX_LIST_FREE_BOX, true);
+               if (slen < 0) return -1;
+
+               MEM(vb = fr_value_box_alloc_null(ctx));
+               vlen = fr_value_box_from_str(vb, vb, cast, NULL,
+                                            fr_sbuff_start(agg), fr_sbuff_used(agg),
+                                            NULL, tainted);
+               if ((vlen < 0) || (slen != vlen)) return -1;
+
+               fr_dlist_insert_tail(list, vb);
+               break;
+
+       case FR_TYPE_STRING:
+       case FR_TYPE_OCTETS:
+               return fr_value_box_list_concat_in_place(vb, vb, list, cast,
+                                                        FR_VALUE_BOX_LIST_FREE_BOX, true, SIZE_MAX);
+       case FR_TYPE_STRUCTURAL:
+               fr_strerror_printf("Cannot cast to structural type '%s'",
+                                  fr_type_to_str(cast));
+               return -1;
+       }
+
+       return 0;
+}
+
 int tmpl_global_init(void)
 {
        if (fr_dict_autoload(tmpl_dict) < 0) {
index bb3070a0e418f100a2e32e1652d2c70086fc4850..41a3ef77bfba4862323ad1f259c4ed92a61badc6 100644 (file)
@@ -1038,6 +1038,14 @@ xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_exp_head_
                                fr_value_box_copy(value, value, tmpl_value(node->vpt)); /* Also dups taint */
                                fr_dlist_insert_tail(&result, value);
 
+                               /*
+                                *      Cast the results if necessary.
+                                */
+                               if (tmpl_eval_cast(ctx, &result, node->vpt) < 0) goto fail;
+
+                               fr_dlist_move(out->dlist, &result);
+                               continue;
+
                        } else if (tmpl_is_attr(node->vpt) ||  tmpl_is_list(node->vpt)) {
                                if (node->fmt[0] == '&') {
                                        XLAT_DEBUG("** [%i] %s(attribute) - %s", unlang_interpret_stack_depth(request), __FUNCTION__,
@@ -1082,61 +1090,6 @@ xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_exp_head_
                                fr_assert(0);
                        }
 
-                       /*
-                        *      Apply a cast to the results if required.
-                        */
-                       if (tmpl_rules_cast(node->vpt) != FR_TYPE_NULL) {
-                               fr_type_t cast = tmpl_rules_cast(node->vpt);
-                               fr_value_box_t *vb;
-                               bool tainted;
-
-                               vb = fr_dlist_head(&result);
-
-                               switch (cast) {
-                               case FR_TYPE_STRING:
-                               case FR_TYPE_OCTETS:
-                                       if (fr_value_box_list_concat_in_place(vb, vb, &result, cast,
-                                                                             FR_VALUE_BOX_LIST_FREE_BOX, true, SIZE_MAX) < 0) {
-                                               goto fail;
-                                       }
-                                       break;
-
-                               default:
-                                       /*
-                                        *      One box, we cast it as the destination type.
-                                        *
-                                        *      Many boxes, turn them into strings, and try to parse it as the
-                                        *      output type.
-                                        */
-                                       if (!fr_dlist_next(&result, vb)) {
-                                               if (fr_value_box_cast_in_place(vb, vb, cast, NULL) < 0) goto fail;
-
-                                       } else {
-                                               ssize_t slen, vlen;
-                                               fr_sbuff_t *agg;
-
-                                               FR_SBUFF_TALLOC_THREAD_LOCAL(&agg, 256, 256);
-
-                                               slen = fr_value_box_list_concat_as_string(&tainted, agg, &result, NULL, 0, NULL,
-                                                                                         FR_VALUE_BOX_LIST_FREE_BOX, true);
-                                               if (slen < 0) goto fail;
-
-                                               MEM(vb = fr_value_box_alloc_null(ctx));
-                                               vlen = fr_value_box_from_str(vb, vb, cast, NULL,
-                                                                            fr_sbuff_start(agg), fr_sbuff_used(agg),
-                                                                            NULL, tainted);
-                                               if ((vlen < 0) || (slen != vlen)) goto fail;
-
-                                               fr_dlist_insert_tail(&result, vb);
-                                       }
-                                       break;
-
-                               case FR_TYPE_STRUCTURAL:
-                                       fr_assert(0);
-                                       goto fail;
-                               }
-                       }
-
                        xlat_debug_log_list_result(request, &result);
                        fr_dlist_move(out->dlist, &result);
                        continue;