httpd-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From s.@apache.org
Subject svn commit: r1204087 - in /httpd/httpd/trunk: include/ap_expr.h include/ap_mmn.h server/util_expr_eval.c server/util_expr_parse.c server/util_expr_parse.y
Date Sat, 19 Nov 2011 21:58:49 GMT
Author: sf
Date: Sat Nov 19 21:58:48 2011
New Revision: 1204087

URL: http://svn.apache.org/viewvc?rev=1204087&view=rev
Log:
Limit recursion in ap_expr evaluation to avoid unbounded stack usage
* evaluate chains of ||, &&, and string concatenation non-recursively
* limit other types of recursion to 20 levels
* avoid some string copies if concatenating more than 2 strings

Modified:
    httpd/httpd/trunk/include/ap_expr.h
    httpd/httpd/trunk/include/ap_mmn.h
    httpd/httpd/trunk/server/util_expr_eval.c
    httpd/httpd/trunk/server/util_expr_parse.c
    httpd/httpd/trunk/server/util_expr_parse.y

Modified: httpd/httpd/trunk/include/ap_expr.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_expr.h?rev=1204087&r1=1204086&r2=1204087&view=diff
==============================================================================
--- httpd/httpd/trunk/include/ap_expr.h (original)
+++ httpd/httpd/trunk/include/ap_expr.h Sat Nov 19 21:58:48 2011
@@ -130,6 +130,8 @@ typedef struct {
     const char **result_string;
     /** Arbitrary context data provided by the caller for custom functions */
     void *data;
+    /** The current recursion level */
+    int reclvl;
 } ap_expr_eval_ctx_t;
 
 /**

Modified: httpd/httpd/trunk/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_mmn.h?rev=1204087&r1=1204086&r2=1204087&view=diff
==============================================================================
--- httpd/httpd/trunk/include/ap_mmn.h (original)
+++ httpd/httpd/trunk/include/ap_mmn.h Sat Nov 19 21:58:48 2011
@@ -366,6 +366,7 @@
  *                         and ap_unescape_urlencoded().
  * 20111025.2 (2.3.15-dev) Add ap_lua_ssl_val to mod_lua
  * 20111118.0 (2.5.0-dev)  Add conn_rec to error_log hook
+ * 20111118.1 (2.5.0-dev)  Add reclvl to ap_expr_eval_ctx_t
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -373,7 +374,7 @@
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20111118
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 0                   /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 1                   /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a

Modified: httpd/httpd/trunk/server/util_expr_eval.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_expr_eval.c?rev=1204087&r1=1204086&r2=1204087&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util_expr_eval.c (original)
+++ httpd/httpd/trunk/server/util_expr_eval.c Sat Nov 19 21:58:48 2011
@@ -56,10 +56,30 @@ static void expr_dump_tree(const ap_expr
                            int loglevel, int indent);
 #endif
 
+/*
+ * To reduce counting overhead, we only count calls to
+ * ap_expr_eval_word() and ap_expr_eval(). This means the actual
+ * recursion may be twice as deep.
+ */
+#define AP_EXPR_MAX_RECURSION   20
+static int inc_rec(ap_expr_eval_ctx_t *ctx)
+{
+    if (ctx->reclvl < AP_EXPR_MAX_RECURSION) {
+        ctx->reclvl++;
+        return 0;
+    }
+    *ctx->err = "Recursion limit reached";
+    /* short circuit further evaluation */
+    ctx->reclvl = INT_MAX;
+    return 1;
+}
+
 static const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
                                      const ap_expr_t *node)
 {
     const char *result = "";
+    if (inc_rec(ctx))
+        return result;
     switch (node->node_op) {
     case op_Digit:
     case op_String:
@@ -68,17 +88,41 @@ static const char *ap_expr_eval_word(ap_
     case op_Var:
         result = ap_expr_eval_var(ctx, node->node_arg1, node->node_arg2);
         break;
-    case 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)
-            result = s2;
-        else if (!*s2)
-            result = s1;
-        else
-            result = apr_pstrcat(ctx->p, s1, s2, NULL);
+    case op_Concat:
+        if (((ap_expr_t *)node->node_arg2)->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)
+                result = s2;
+            else if (!*s2)
+                result = s1;
+            else
+                result = apr_pstrcat(ctx->p, s1, s2, NULL);
+        }
+        else {
+            const ap_expr_t *nodep = node;
+            int i = 1;
+            struct iovec *vec;
+            do {
+                nodep = nodep->node_arg2;
+                i++;
+            } while (nodep->node_op == op_Concat);
+            vec = apr_palloc(ctx->p, i * sizeof(struct iovec));
+            nodep = node;
+            i = 0;
+            do {
+                vec[i].iov_base = (void *)ap_expr_eval_word(ctx,
+                                                            nodep->node_arg1);
+                vec[i].iov_len = strlen(vec[i].iov_base);
+                i++;
+                nodep = nodep->node_arg2;
+            } 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);
+            i++;
+            result = apr_pstrcatv(ctx->p, vec, i, NULL);
+        }
         break;
-    }
     case op_StringFuncCall: {
         const ap_expr_t *info = node->node_arg1;
         const ap_expr_t *args = node->node_arg2;
@@ -96,6 +140,7 @@ static const char *ap_expr_eval_word(ap_
     }
     if (!result)
         result = "";
+    ctx->reclvl--;
     return result;
 }
 
@@ -657,30 +702,81 @@ static int ap_expr_eval(ap_expr_eval_ctx
 {
     const ap_expr_t *e1 = node->node_arg1;
     const ap_expr_t *e2 = node->node_arg2;
-    switch (node->node_op) {
-    case op_True:
-        return 1;
-    case op_False:
-        return 0;
-    case op_Not:
-        return (!ap_expr_eval(ctx, e1));
-    case op_Or:
-        return (ap_expr_eval(ctx, e1) || ap_expr_eval(ctx, e2));
-    case op_And:
-        return (ap_expr_eval(ctx, e1) && ap_expr_eval(ctx, e2));
-    case op_UnaryOpCall:
-        return ap_expr_eval_unary_op(ctx, e1, e2);
-    case op_BinaryOpCall:
-        return ap_expr_eval_binary_op(ctx, e1, e2);
-    case op_Comp:
-        if (ctx->info->flags & AP_EXPR_FLAG_SSL_EXPR_COMPAT)
-            return ssl_expr_eval_comp(ctx, e1);
-        else
-            return ap_expr_eval_comp(ctx, e1);
-    default:
-        *ctx->err = "Internal evaluation error: Unknown expression node";
-        return FALSE;
+    int result = FALSE;
+    if (inc_rec(ctx))
+        return result;
+    while (1) {
+        switch (node->node_op) {
+        case op_True:
+            result ^= TRUE;
+            goto out;
+        case op_False:
+            ctx->reclvl--;
+            result ^= FALSE;
+            goto out;
+        case op_Not:
+            result = !result;
+            node = e1;
+            break;
+        case op_Or:
+            do {
+                if (e1->node_op == op_Not) {
+                    if (!ap_expr_eval(ctx, e1->node_arg1)) {
+                        result ^= TRUE;
+                        goto out;
+                    }
+                }
+                else {
+                    if (ap_expr_eval(ctx, e1)) {
+                        ctx->reclvl--;
+                        result ^= TRUE;
+                        goto out;
+                    }
+                }
+                node = node->node_arg2;
+                e1 = node->node_arg1;
+            } while (node->node_op == op_Or);
+            break;
+        case op_And:
+            do {
+                if (e1->node_op == op_Not) {
+                    if (ap_expr_eval(ctx, e1->node_arg1)) {
+                        result ^= FALSE;
+                        goto out;
+                    }
+                }
+                else {
+                    if (!ap_expr_eval(ctx, e1)) {
+                        result ^= FALSE;
+                        goto out;
+                    }
+                }
+                node = node->node_arg2;
+                e1 = node->node_arg1;
+            } while (node->node_op == op_And);
+            break;
+        case op_UnaryOpCall:
+            result ^= ap_expr_eval_unary_op(ctx, e1, e2);
+            goto out;
+        case op_BinaryOpCall:
+            result ^= ap_expr_eval_binary_op(ctx, e1, e2);
+            goto out;
+        case op_Comp:
+            if (ctx->info->flags & AP_EXPR_FLAG_SSL_EXPR_COMPAT)
+                result ^= ssl_expr_eval_comp(ctx, e1);
+            else
+                result ^= ap_expr_eval_comp(ctx, e1);
+            goto out;
+        default:
+            *ctx->err = "Internal evaluation error: Unknown expression node";
+            goto out;
+        }
+        e1 = node->node_arg1;
+        e2 = node->node_arg2;
     }
+out:
+    ctx->reclvl--;
+    return result;
 }
 
 AP_DECLARE(int) ap_expr_exec(request_rec *r, const ap_expr_info_t *info,
@@ -704,6 +800,7 @@ AP_DECLARE(int) ap_expr_exec_ctx(ap_expr
         AP_DEBUG_ASSERT(ctx->re_source != NULL);
         AP_DEBUG_ASSERT(ctx->re_nmatch > 0);
     }
+    ctx->reclvl = 0;
 
     *ctx->err = NULL;
     if (ctx->info->flags & AP_EXPR_FLAG_STRING_RESULT) {

Modified: httpd/httpd/trunk/server/util_expr_parse.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_expr_parse.c?rev=1204087&r1=1204086&r2=1204087&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util_expr_parse.c (original)
+++ httpd/httpd/trunk/server/util_expr_parse.c Sat Nov 19 21:58:48 2011
@@ -591,9 +591,9 @@ static const yytype_int8 yypact[] =
       25,   -35,    79,   -17,   -35,    -8,    60,    60,    43,    43,
       43,    43,    43,    43,    43,     5,     5,     0,    43,    43,
       43,    43,    43,    43,    43,   -35,   -27,   -35,   -35,    73,
-     -35,     3,   -35,    25,    25,    25,    25,    25,    25,    25,
+     -35,    86,     3,    25,    25,    25,    25,    25,    25,    25,
      -35,   -35,   -35,   -35,    23,    43,   -35,   -35,    25,    25,
-      25,    25,    25,    25,   -35,   -35,   106,    43,    85,    25,
+      25,    25,    25,    25,    25,   -35,   106,    43,    85,    25,
      -35,   -21,   -35,    43,   -35,    25
 };
 

Modified: httpd/httpd/trunk/server/util_expr_parse.y
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_expr_parse.y?rev=1204087&r1=1204086&r2=1204087&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util_expr_parse.y (original)
+++ httpd/httpd/trunk/server/util_expr_parse.y Sat Nov 19 21:58:48 2011
@@ -81,10 +81,10 @@
 %token  T_OP_AND
 %token  T_OP_NOT
 
-%left   T_OP_OR
-%left   T_OP_AND
-%left   T_OP_NOT
-%left   T_OP_CONCAT
+%right  T_OP_OR
+%right  T_OP_AND
+%right  T_OP_NOT
+%right  T_OP_CONCAT
 
 %type   <exVal>   expr
 %type   <exVal>   comparison



Mime
View raw message