From: Arran Cudbard-Bell Date: Wed, 17 Jun 2015 17:01:44 +0000 (-0400) Subject: Allow expr to work on attribute refs that may be converted into integers (like IPv4... X-Git-Tag: release_3_0_9~140 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4732f6ccb920758f5d9072f30ac68b4c520257ba;p=thirdparty%2Ffreeradius-server.git Allow expr to work on attribute refs that may be converted into integers (like IPv4 addresses and Date types) --- diff --git a/src/modules/rlm_expr/rlm_expr.c b/src/modules/rlm_expr/rlm_expr.c index fd3640a4890..71b83122e94 100644 --- a/src/modules/rlm_expr/rlm_expr.c +++ b/src/modules/rlm_expr/rlm_expr.c @@ -224,54 +224,48 @@ static bool get_number(REQUEST *request, char const **string, int64_t *answer) * Look for an attribute. */ if (*p == '&') { - ssize_t slen; - VALUE_PAIR *vp; - vp_tmpl_t vpt; + ssize_t slen; + VALUE_PAIR *vp; + vp_tmpl_t vpt; p += 1; slen = tmpl_from_attr_substr(&vpt, p, REQUEST_CURRENT, PAIR_LIST_REQUEST, false, false); if (slen < 0) { - RDEBUG("Failed parsing attribute name '%s': %s", p, fr_strerror()); + REDEBUG("Failed parsing attribute name '%s': %s", p, fr_strerror()); return false; } p += slen; if (tmpl_find_vp(&vp, request, &vpt) < 0) { - RDEBUG("Can't find &%s", vpt.tmpl_da->name); + RWDEBUG("Can't find &%.*s. Using 0 as operand value", (int)vpt.len, vpt.name); x = 0; goto done; } - switch (vp->da->type) { - default: - RDEBUG("WARNING: Non-integer attribute %s", vp->da->name); - x = 0; - break; + if (vp->da->type != PW_TYPE_INTEGER64) { + value_data_t value; - case PW_TYPE_INTEGER64: - /* - * FIXME: error out if the number is too large. - */ - x = vp->vp_integer64; - break; - - case PW_TYPE_INTEGER: - x = vp->vp_integer; - break; - - case PW_TYPE_SIGNED: - x = vp->vp_signed; - break; - - case PW_TYPE_SHORT: - x = vp->vp_short; - break; + if (value_data_cast(vp, &value, PW_TYPE_INTEGER64, NULL, vp->da->type, vp->da, &vp->data) < 0) { + REDEBUG("Failed converting &%.*s to an integer value: %s", (int) vpt.len, + vpt.name, fr_strerror()); + return false; + } + if (value.integer64 > INT64_MAX) { + overflow: + REDEBUG("Value of &%.*s (%"PRIu64 ") would overflow a signed 64bit integer " + "(our internal arithmetic type)", (int)vpt.len, vpt.name, value.integer64); + return false; + } + x = (int64_t)value.integer64; - case PW_TYPE_BYTE: - x = vp->vp_byte; - break; + RINDENT(); + RDEBUG3("&%.*s --> %" PRIu64, (int)vpt.len, vpt.name, x); + REXDENT(); + } else { + if (vp->vp_integer64 > INT64_MAX) goto overflow; + x = (int64_t)vp->vp_integer64; } goto done; diff --git a/src/tests/keywords/expr b/src/tests/keywords/expr index 34e7ddf0aa8..7645931bdc6 100644 --- a/src/tests/keywords/expr +++ b/src/tests/keywords/expr @@ -34,6 +34,7 @@ update request { Tmp-Integer-0 = 1 Tmp-Integer-1 = 3 Tmp-Integer-2 = 4 + Tmp-Date-0 = "%l" } if ("%{expr: 1 + 2 * &Tmp-Integer-1 + 4}" != 11) { @@ -84,18 +85,24 @@ if ("%{expr: 1 << 2 | 1}" != 5) { } } +if ("%{expr: &Tmp-Date-0}" <= 0) { + update reply { + Filter-Id := "fail-11" + } +} + # # Unary negation # if ("%{expr: 6 + -(1 + 3)}" != 2) { update reply { - Filter-Id := "fail-11" + Filter-Id := "fail-12" } } if ("%{expr: 6 * -&Tmp-Integer-2}" != -24) { update reply { - Filter-Id := "fail-11" + Filter-Id := "fail-13" } }