From: Alan T. DeKok Date: Tue, 5 Jan 2021 16:33:09 +0000 (-0500) Subject: make cond_eval() iterative X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0bc65b7a8685fb0394ca8693afec6f6942eaa9e1;p=thirdparty%2Ffreeradius-server.git make cond_eval() iterative and set c->parent correctly in cond_normalise() --- diff --git a/src/lib/server/cond_eval.c b/src/lib/server/cond_eval.c index 813189b3631..47fb086eea9 100644 --- a/src/lib/server/cond_eval.c +++ b/src/lib/server/cond_eval.c @@ -724,7 +724,6 @@ int cond_eval_map(request_t *request, UNUSED int depth, fr_cond_t const *c) * * @param[in] request the request_t * @param[in] modreturn the previous module return code - * @param[in] depth of the recursion (only used for debugging) * @param[in] c the condition to evaluate * @return * - -1 on failure. @@ -732,9 +731,11 @@ int cond_eval_map(request_t *request, UNUSED int depth, fr_cond_t const *c) * - 0 for "no match". * - 1 for "match". */ -int cond_eval(request_t *request, rlm_rcode_t modreturn, int depth, fr_cond_t const *c) +int cond_eval(request_t *request, rlm_rcode_t modreturn, fr_cond_t const *c) { int rcode = -1; + int depth = 0; + #ifdef WITH_EVAL_DEBUG char buffer[1024]; @@ -757,8 +758,9 @@ int cond_eval(request_t *request, rlm_rcode_t modreturn, int depth, fr_cond_t co break; case COND_TYPE_CHILD: - rcode = cond_eval(request, modreturn, depth + 1, c->data.child); - break; + depth++; + c = c->data.child; + continue; case COND_TYPE_TRUE: rcode = true; @@ -772,6 +774,9 @@ int cond_eval(request_t *request, rlm_rcode_t modreturn, int depth, fr_cond_t co return -1; } + /* + * Errors cause failures. + */ if (rcode < 0) return rcode; if (c->negate) rcode = !rcode; @@ -784,13 +789,13 @@ int cond_eval(request_t *request, rlm_rcode_t modreturn, int depth, fr_cond_t co if (c->next) { switch (c->next->type) { case COND_TYPE_AND: - if (!rcode) return false; + if (!rcode) goto return_to_parent; c = c->next; /* skip the && */ break; case COND_TYPE_OR: - if (rcode) return true; + if (rcode) goto return_to_parent; c = c->next; /* skip the || */ break; @@ -800,6 +805,19 @@ int cond_eval(request_t *request, rlm_rcode_t modreturn, int depth, fr_cond_t co } } + /* + * We've fallen off of the end of this evaluation + * string. Go back up to the parent, and then to + * the next sibling of the parent. + */ + if (!c->next) { +return_to_parent: + c = c->parent; + depth--; + + if (!c) break; /* we have to do this, otherwise the next line will fail */ + } + c = c->next; } diff --git a/src/lib/server/cond_eval.h b/src/lib/server/cond_eval.h index 1f6b0bba461..93b27c2d3b1 100644 --- a/src/lib/server/cond_eval.h +++ b/src/lib/server/cond_eval.h @@ -40,7 +40,7 @@ void cond_debug(fr_cond_t const *cond); int cond_eval_tmpl(request_t *request, int depth, tmpl_t const *vpt); int cond_eval_map(request_t *request, int depth, fr_cond_t const *c); -int cond_eval(request_t *request, rlm_rcode_t modreturn, int depth, fr_cond_t const *c); +int cond_eval(request_t *request, rlm_rcode_t modreturn, fr_cond_t const *c); #ifdef __cplusplus } diff --git a/src/lib/server/cond_tokenize.c b/src/lib/server/cond_tokenize.c index 9c79f6dcdc9..2d72c9ccc98 100644 --- a/src/lib/server/cond_tokenize.c +++ b/src/lib/server/cond_tokenize.c @@ -653,6 +653,7 @@ static int cond_normalise(TALLOC_CTX *ctx, fr_token_t lhs_type, fr_cond_t **c_ou * !(!FOO) --> FOO, etc. */ child->negate = (c->negate != child->negate); + child->parent = c->parent; talloc_free(c); c = child; continue; @@ -666,6 +667,7 @@ static int cond_normalise(TALLOC_CTX *ctx, fr_token_t lhs_type, fr_cond_t **c_ou */ if (!c->next && !c->negate) { (void) talloc_steal(ctx, child); + child->parent = c->parent; talloc_free(c); c = child; continue; diff --git a/src/lib/unlang/condition.c b/src/lib/unlang/condition.c index 9e309834b2d..44ff151342c 100644 --- a/src/lib/unlang/condition.c +++ b/src/lib/unlang/condition.c @@ -42,7 +42,7 @@ static unlang_action_t unlang_if(rlm_rcode_t *p_result, request_t *request) gext = unlang_group_to_cond(g); fr_assert(gext->cond != NULL); - condition = cond_eval(request, *p_result, 0, gext->cond); + condition = cond_eval(request, *p_result, gext->cond); if (condition < 0) { switch (condition) { case -2: