Commit ad4d59a6 authored by Rainer Jung's avatar Rainer Jung
Browse files

Merge r1657685 from trunk:

core: Optimize string concatenation in expression
parser when evaluating a string expression.

We have a relatively small recursion limit of
about 10 operations. This is a compilation
limit (a define). It can be hit if many expr
vars or function calls are concatenated in an
expression that is evaluated as a string not as
a boolean.

The new optimization uses iteration instead of
recursion and is very similar to the
existing one, which optimizes consecutive
concatenations in node2 of the tree. The new
one optimizes consecutive concatenations in
node 1.

Submitted by: rjung
Reviewed by: rjung, ylavic, covener
Backported by: rjung


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1662075 13f79535-47bb-0310-9956-ffa450edef68
parent 8536171b
Loading
Loading
Loading
Loading
+3 −0
Changes for CHANGES: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -2,6 +2,9 @@

Changes with Apache 2.4.13

  *) core: Optimize string concatenation in expression parser when evaluating
     a string expression. [Rainer Jung]

  *) acinclude.m4: Generate #LoadModule directive in default httpd.conf for
     every --enable-mpms-shared. PR 53882.  [olli hauer <ohauer gmx.de>,
     Yann Ylavic]
+0 −11
Changes for STATUS: 0 added lines, 11 removed lines.
Original line number Diff line number Diff line
@@ -112,17 +112,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
     2.4.x patch: trunk works (module CHANGES)
     +1: ylavic, wrowe, minfrin

   * Expression parser: Optimize another concatenation case by using iteration
     instead of recursion.
     We have a relatively small recursion limit of about 10 operations. This
     is a compilation limit (a define). It can be hit if many expr vars or
     function calls are concatenated. The new optimization is very similar to
     the existing one, which optimizes consecutive concatenations in node2 of
     the tree. The new one optimizes consecutive concatenations in node 1.
     trunk patch: http://svn.apache.org/r1657685
     2.4.x patch: trunk works (modulo CHANGES)
     +1: rjung, ylavic, covener

   * Save a few bytes in conf pool when parsing some directives. Use temp_pool
     when applicable.
     trunk patch: http://svn.apache.org/r1657692
+26 −1
Changes for server/util_expr_eval.c: 26 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -96,7 +96,8 @@ static const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
                                  node->node_arg2);
        break;
    case op_Concat:
        if (((ap_expr_t *)node->node_arg2)->node_op != op_Concat) {
        if (((ap_expr_t *)node->node_arg2)->node_op != op_Concat &&
            ((ap_expr_t *)node->node_arg1)->node_op != op_Concat) {
            const char *s1 = ap_expr_eval_word(ctx, node->node_arg1);
            const char *s2 = ap_expr_eval_word(ctx, node->node_arg2);
            if (!*s1)
@@ -106,6 +107,30 @@ static const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
            else
                result = apr_pstrcat(ctx->p, s1, s2, NULL);
        }
        else if (((ap_expr_t *)node->node_arg1)->node_op == op_Concat) {
            const ap_expr_t *nodep = node;
            int n;
            int i = 1;
            struct iovec *vec;
            do {
                nodep = nodep->node_arg1;
                i++;
            } while (nodep->node_op == op_Concat);
            vec = apr_palloc(ctx->p, i * sizeof(struct iovec));
            n = i;
            nodep = node;
            i--;
            do {
                vec[i].iov_base = (void *)ap_expr_eval_word(ctx,
                                                            nodep->node_arg2);
                vec[i].iov_len = strlen(vec[i].iov_base);
                i--;
                nodep = nodep->node_arg1;
            } while (nodep->node_op == op_Concat);
            vec[i].iov_base = (void *)ap_expr_eval_word(ctx, nodep);
            vec[i].iov_len = strlen(vec[i].iov_base);
            result = apr_pstrcatv(ctx->p, vec, n, NULL);
        }
        else {
            const ap_expr_t *nodep = node;
            int i = 1;