-------- Original-Nachricht --------
Betreff: 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
Datum: Sat, 19 Nov 2011 21:58:49 GMT
Von: [email protected]
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/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
@@ -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;
Why all these XOR operations and no simple assignments?
+ goto out;
+ case op_False:
+ ctx->reclvl--;
Why this? We already decrement below.
+ 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--;
Why this? We already decrement below.
+ 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,