From: Stefan Fritsch Date: Sat, 13 Aug 2011 09:59:43 +0000 (+0000) Subject: Do proper length checks in the expression scanner. This allows to remove the X-Git-Tag: 2.3.15~385 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8281a318cfa1f8a88960beae2ea3b37400f461aa;p=thirdparty%2Fapache%2Fhttpd.git Do proper length checks in the expression scanner. This allows to remove the 8K length limit for expressions. Strings/Regexs in an expression are still limited to 8K, though. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1157362 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/server/util_expr_eval.c b/server/util_expr_eval.c index 5730ebf3655..5e3586e4190 100644 --- a/server/util_expr_eval.c +++ b/server/util_expr_eval.c @@ -318,15 +318,6 @@ AP_DECLARE(const char *) ap_expr_parse(apr_pool_t *pool, apr_pool_t *ptemp, ctx.lookup_fn = lookup_fn ? lookup_fn : ap_expr_lookup_default; ctx.at_start = 1; - - /* - * Be sure to avoid overflows in the scanner. In practice the input length - * will be limited by the config file parser, anyway. - * XXX: The scanner really should do proper buffer overflow checks - */ - if (ctx.inputlen >= MAX_STRING_LEN) - return "Expression too long"; - ap_expr_yylex_init(&ctx.scanner); ap_expr_yyset_extra(&ctx, ctx.scanner); rc = ap_expr_yyparse(&ctx); diff --git a/server/util_expr_parse.y b/server/util_expr_parse.y index 59dea8aa88c..6ba19dd9c46 100644 --- a/server/util_expr_parse.y +++ b/server/util_expr_parse.y @@ -152,6 +152,7 @@ words : word { $$ = ap_expr_make(op_ListElement, $1, string : string strpart { $$ = ap_expr_make(op_Concat, $1, $2, ctx); } | strpart { $$ = $1; } + | T_ERROR { YYABORT; } ; strpart : T_STRING { $$ = ap_expr_make(op_String, $1, NULL, ctx); } diff --git a/server/util_expr_scan.l b/server/util_expr_scan.l index 607af140735..513236a940a 100644 --- a/server/util_expr_scan.l +++ b/server/util_expr_scan.l @@ -60,12 +60,18 @@ #define YY_EXTRA_TYPE ap_expr_parse_ctx_t* -#define PERROR(msg) yyextra->error2 = msg ; return T_ERROR; +#define PERROR(msg) do { yyextra->error2 = msg ; return T_ERROR; } while (0) #define str_ptr (yyextra->scan_ptr) #define str_buf (yyextra->scan_buf) #define str_del (yyextra->scan_del) +#define STR_APPEND(c) do { \ + *str_ptr++ = (c); \ + if (str_ptr >= str_buf + sizeof(str_buf)) \ + PERROR("String too long"); \ + } while (0) + %} @@ -126,7 +132,7 @@ } } else { - *str_ptr++ = yytext[0]; + STR_APPEND(yytext[0]); } } \n { @@ -156,20 +162,18 @@ PERROR("Escape sequence out of bound"); } else { - *str_ptr++ = result; + STR_APPEND(result); } } \\[0-9]+ { PERROR("Bad escape sequence"); } -\\n { *str_ptr++ = '\n'; } -\\r { *str_ptr++ = '\r'; } -\\t { *str_ptr++ = '\t'; } -\\b { *str_ptr++ = '\b'; } -\\f { *str_ptr++ = '\f'; } -\\(.|\n) { - *str_ptr++ = yytext[1]; -} +\\n { STR_APPEND('\n'); } +\\r { STR_APPEND('\r'); } +\\t { STR_APPEND('\t'); } +\\b { STR_APPEND('\b'); } +\\f { STR_APPEND('\f'); } +\\(.|\n) { STR_APPEND(yytext[1]); } /* regexp backref inside string/arg */ [$][0-9] { @@ -189,8 +193,10 @@ [^\\\n"'%}$]+ { char *cp = yytext; - while (*cp != '\0') - *str_ptr++ = *cp++; + while (*cp != '\0') { + STR_APPEND(*cp); + cp++; + } } /* variable inside string/arg */ @@ -210,11 +216,11 @@ } [%$] { - *str_ptr++ = yytext[0]; + STR_APPEND(yytext[0]); } [%}$] { - *str_ptr++ = yytext[0]; + STR_APPEND(yytext[0]); } %\{ { @@ -286,6 +292,8 @@ } else { *regex_ptr++ = yytext[0]; + if (regex_ptr >= regex_buf + sizeof(regex_buf)) + PERROR("Regexp too long"); } } i {