a = &one;
}
- if (b->type != FR_TYPE_TIME_DELTA) {
+ if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
+ if (fr_value_box_cast(ctx, &two, FR_TYPE_UINT8, dst->enumv, b) < 0) return -1;
+ b = &two;
+
+ } else if (b->type != FR_TYPE_TIME_DELTA) {
if (fr_value_box_cast(NULL, &two, FR_TYPE_TIME_DELTA, dst->enumv, b) < 0) return -1;
b = &two;
}
dst->vb_time_delta = fr_time_delta_wrap(when);
break;
+ case T_RSHIFT:
+ when = fr_time_delta_unwrap(a->vb_time_delta) >> b->vb_uint8;
+ dst->vb_time_delta = fr_time_delta_wrap(when);
+ break;
+
+ case T_LSHIFT:
+ if (b->vb_uint8 >= 64) return ERR_OVERFLOW;
+
+ when = fr_time_delta_unwrap(a->vb_time_delta) << b->vb_uint8;
+ dst->vb_time_delta = fr_time_delta_wrap(when);
+ break;
+
default:
return ERR_INVALID; /* invalid operator */
}
a = &one;
}
- if (b->type != FR_TYPE_OCTETS) {
+ if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
+ if (fr_value_box_cast(ctx, &two, FR_TYPE_UINT32, dst->enumv, b) < 0) return -1;
+ b = &two;
+
+ } else if (b->type != FR_TYPE_OCTETS) {
if (fr_value_box_cast(ctx, &two, FR_TYPE_OCTETS, dst->enumv, b) < 0) return -1;
b = &two;
}
fr_value_box_memdup_shallow(dst, dst->enumv, buf, a->vb_length, a->tainted | b->tainted);
break;
+ case T_RSHIFT:
+ if (b->vb_uint32 > a->vb_length) return ERR_UNDERFLOW;
+
+ len = a->vb_length - b->vb_uint32;
+ buf = talloc_array(ctx, uint8_t, len);
+ if (!buf) goto oom;
+
+ memcpy(buf, a->vb_octets, len);
+
+ fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, a->tainted);
+ break;
+
+ case T_LSHIFT:
+ if (b->vb_uint32 > a->vb_length) return ERR_OVERFLOW;
+
+ len = a->vb_length - b->vb_uint32;
+
+ buf = talloc_array(ctx, uint8_t, len);
+ if (!buf) goto oom;
+
+ memcpy(buf, a->vb_octets + b->vb_uint32, len);
+
+ fr_value_box_memdup_shallow(dst, dst->enumv, buf, len, a->tainted);
+ break;
+
default:
return ERR_INVALID; /* invalid operator */
}
a = &one;
}
- if (b->type != FR_TYPE_STRING) {
+ if ((op == T_RSHIFT) || (op == T_LSHIFT)) {
+ if (fr_value_box_cast(ctx, &two, FR_TYPE_UINT32, dst->enumv, b) < 0) return -1;
+ b = &two;
+
+ } else if (b->type != FR_TYPE_STRING) {
if (fr_value_box_cast(ctx, &two, FR_TYPE_STRING, dst->enumv, b) < 0) return -1;
b = &two;
}
return -1;
}
+ len = a->vb_length + b->vb_length;
memcpy(buf, b->vb_strvalue, b->vb_length);
memcpy(buf + b->vb_length, a->vb_strvalue, a->vb_length);
- buf[a->vb_length + b->vb_length] = '\0';
+ buf[len] = '\0';
- fr_value_box_strdup_shallow(dst, dst->enumv, buf, a->tainted | b->tainted);
+ fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, a->tainted | b->tainted);
break;
case T_ADD:
buf = talloc_array(ctx, char, len + 1);
if (!buf) goto oom;
+ len = a->vb_length + b->vb_length;
memcpy(buf, a->vb_strvalue, a->vb_length);
memcpy(buf + a->vb_length, b->vb_strvalue, b->vb_length);
- buf[a->vb_length + b->vb_length] = '\0';
+ buf[len] = '\0';
- fr_value_box_strdup_shallow(dst, dst->enumv, buf, a->tainted | b->tainted);
+ fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, a->tainted | b->tainted);
break;
case T_SUB:
memcpy(buf, a->vb_strvalue, len);
buf[len] = '\0';
- fr_value_box_strdup_shallow(dst, dst->enumv, buf, a->tainted | b->tainted);
+ fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, a->tainted | b->tainted);
+ break;
+
+ case T_RSHIFT:
+ if (b->vb_uint32 > a->vb_length) return ERR_UNDERFLOW;
+
+ len = a->vb_length - b->vb_uint32;
+ buf = talloc_array(ctx, char, len + 1);
+ if (!buf) goto oom;
+
+ memcpy(buf, a->vb_strvalue, len);
+ buf[len] = '\0';
+
+ fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, a->tainted);
+ break;
+
+ case T_LSHIFT:
+ if (b->vb_uint32 > a->vb_length) return ERR_OVERFLOW;
+
+ len = a->vb_length - b->vb_uint32;
+
+ buf = talloc_array(ctx, char, len + 1);
+ if (!buf) goto oom;
+
+ memcpy(buf, a->vb_strvalue + b->vb_uint32, len);
+ buf[len] = '\0';
+
+ fr_value_box_bstrndup_shallow(dst, dst->enumv, buf, len, a->tainted);
break;
default:
case T_OR: \
dst->vb_ ## _t = in1->vb_ ## _t | in2->vb_ ## _t; \
break; \
+ \
+ case T_RSHIFT: \
+ if (in2->vb_uint8 > (8 * sizeof(in1->vb_ ## _t))) return ERR_UNDERFLOW; \
+ \
+ dst->vb_ ## _t = in1->vb_ ## _t >> in2->vb_uint8; \
+ break; \
+ \
+ case T_LSHIFT: \
+ if (in2->vb_uint8 >= (8 * sizeof(in1->vb_ ## _t))) return ERR_OVERFLOW; \
+ \
+ dst->vb_ ## _t = in1->vb_ ## _t << in2->vb_uint8; \
+ break; \
\
default: \
return ERR_INVALID; \
case T_ADD:
case T_SUB:
+ case T_MUL:
+ case T_DIV:
+ case T_AND:
+ case T_OR:
+ case T_RSHIFT:
+ case T_LSHIFT:
if (a->type == b->type) {
hint = a->type;
break;
case T_AND:
case T_OR:
case T_OP_PREPEND:
+ case T_RSHIFT:
+ case T_LSHIFT:
fr_assert(hint != FR_TYPE_NULL);
func = calc_type[hint];
rcode = fr_value_calc_binary_op(ctx, &out, dst->type, dst, T_AND, src);
break;
+ case T_OP_RSHIFT_EQ:
+ rcode = fr_value_calc_binary_op(ctx, &out, dst->type, dst, T_RSHIFT, src);
+ break;
+
+ case T_OP_LSHIFT_EQ:
+ rcode = fr_value_calc_binary_op(ctx, &out, dst->type, dst, T_LSHIFT, src);
+ break;
+
default:
invalid:
rcode = ERR_INVALID;