]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Better method of un-marshalling values from mRuby to FreeRADIUS
authorNick Porter <nick@portercomputing.co.uk>
Tue, 5 Aug 2025 11:29:39 +0000 (12:29 +0100)
committerNick Porter <nick@portercomputing.co.uk>
Tue, 5 Aug 2025 11:29:39 +0000 (12:29 +0100)
src/modules/rlm_mruby/mruby.c

index fb7bb0de1926547e498246d971d0559ba2190b5d..441d2b1f9389eb7164e30c9af9affaf40d4a32c8 100644 (file)
@@ -321,91 +321,52 @@ static void mruby_pair_parent_build(mrb_state *mrb, mruby_pair_t *pair)
  */
 static void mruby_ruby_to_pair_value(mrb_state *mrb, mrb_value *value, fr_pair_t *vp)
 {
-       switch (vp->vp_type) {
-       case FR_TYPE_STRING:
-               *value = mrb_obj_as_string(mrb, *value);
-               fr_pair_value_clear(vp);
-               fr_pair_value_bstrndup(vp, RSTRING_PTR(*value), RSTRING_LEN(*value), true);
-               break;
+       fr_value_box_t  *vb = NULL;
 
-       case FR_TYPE_OCTETS:
-               *value = mrb_obj_as_string(mrb, *value);
-               fr_pair_value_clear(vp);
-               fr_pair_value_memdup(vp, (uint8_t *)RSTRING_PTR(*value), RSTRING_LEN(*value), true);
+       /*
+        *  Convert the type provided by mRuby to the largest containing FreeRADIUS type
+        */
+       switch (mrb_type(*value)) {
+       case MRB_TT_INTEGER:
+               MEM(vb = fr_value_box_alloc(NULL, FR_TYPE_INT64, NULL));
+               vb->vb_int64 = mrb_integer(*value);
                break;
 
-#define RUBYSETINT(_size)      case FR_TYPE_INT ## _size: \
-       if (mrb_type(*value) != MRB_TT_INTEGER) mrb_raise(mrb, E_ARGUMENT_ERROR, "Integer value required"); \
-       vp->vp_int ## _size = mrb_integer(*value); \
-       break;
-       RUBYSETINT(8)
-       RUBYSETINT(16)
-       RUBYSETINT(32)
-       RUBYSETINT(64)
-
-#define RUBYSETUINT(_size)     case FR_TYPE_UINT ## _size: \
-       if (mrb_type(*value) != MRB_TT_INTEGER) mrb_raise(mrb, E_ARGUMENT_ERROR, "Integer value required"); \
-       vp->vp_uint ## _size = mrb_integer(*value); \
-       break;
-       RUBYSETUINT(8)
-       RUBYSETUINT(16)
-       RUBYSETUINT(32)
-       RUBYSETUINT(64)
-
-#define RUBYSETFLOAT(_size)    case FR_TYPE_FLOAT ## _size: \
-       switch (mrb_type(*value)) { \
-       case MRB_TT_FLOAT: \
-               vp->vp_float ## _size = mrb_float(*value); \
-               break; \
-       case MRB_TT_INTEGER: \
-               vp->vp_float ## _size = mrb_integer(*value); \
-               break; \
-       default: \
-               mrb_raise(mrb, E_ARGUMENT_ERROR, "Float or integer value required"); \
-       } \
-       break;
-       RUBYSETFLOAT(32)
-       RUBYSETFLOAT(64)
-
-       case FR_TYPE_SIZE:
-               if (mrb_type(*value) != MRB_TT_INTEGER) {
-                       mrb_raise(mrb, E_ARGUMENT_ERROR, "Integer value required");
-               }
-               vp->vp_size = mrb_integer(*value);
+       case MRB_TT_FLOAT:
+               MEM(vb = fr_value_box_alloc(NULL, FR_TYPE_FLOAT64, NULL));
+               vb->vb_float64 = mrb_float(*value);
                break;
 
-       case FR_TYPE_BOOL:
-               if (mrb_type(*value) == MRB_TT_TRUE) {
-                       vp->vp_bool = true;
-               } else if (mrb_type(*value) == MRB_TT_FALSE) {
-                       vp->vp_bool = false;
-               } else {
-                       mrb_raise(mrb, E_ARGUMENT_ERROR, "Boolean value required");
-               }
+       case MRB_TT_STRING:
+               MEM(vb = fr_value_box_alloc(NULL, FR_TYPE_STRING, NULL));
+               fr_value_box_bstrndup_dbuff(vb, vb, NULL,
+                                           &FR_DBUFF_TMP((uint8_t *)RSTRING_PTR(*value), RSTRING_LEN(*value)),
+                                           RSTRING_LEN(*value), true);
                break;
 
-       case FR_TYPE_ETHERNET:
-       case FR_TYPE_IPV4_ADDR:
-       case FR_TYPE_IPV6_ADDR:
-       case FR_TYPE_IPV4_PREFIX:
-       case FR_TYPE_IPV6_PREFIX:
-       case FR_TYPE_COMBO_IP_ADDR:
-       case FR_TYPE_COMBO_IP_PREFIX:
-       case FR_TYPE_IFID:
-       case FR_TYPE_TIME_DELTA:
-       case FR_TYPE_DATE:
-       case FR_TYPE_ATTR:
-
-               *value = mrb_obj_as_string(mrb, *value);
-               if (fr_pair_value_from_str(vp, RSTRING_PTR(*value), RSTRING_LEN(*value), NULL, false) < 0) {
-                       mrb_raise(mrb, E_RUNTIME_ERROR, "Failed populating pair");
-               }
+       case MRB_TT_TRUE:
+               MEM(vb = fr_value_box_alloc(NULL, FR_TYPE_BOOL, NULL));
+               vb->vb_bool = true;
                break;
 
-       case FR_TYPE_NON_LEAF:
-               fr_assert(0);
+       case MRB_TT_FALSE:
+               MEM(vb = fr_value_box_alloc(NULL, FR_TYPE_BOOL, NULL));
+               vb->vb_bool = false;
                break;
+
+       default:
+               mrb_raise(mrb, E_ARGUMENT_ERROR, "Unsupported value type");
+       }
+
+       /*
+        *  Cast the converted value to the required type for the pair
+        */
+       fr_pair_value_clear(vp);
+       if (fr_value_box_cast(vp, &vp->data, vp->vp_type, vp->da, vb) < 0) {
+               talloc_free(vb);
+               mrb_raisef(mrb, E_ARGUMENT_ERROR, "Failed casting ruby value to %s", fr_type_to_str(vp->vp_type));
        }
+       talloc_free(vb);
 }
 
 /** Set a value pair from mruby