From: Sander Striker Date: Fri, 24 Oct 2003 16:19:32 +0000 (+0000) Subject: Fold in the CAN-2003-0542 regex patch. X-Git-Tag: 2.0.48~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bb9b68b84dcd85378fa16b85dc0413f415031816;p=thirdparty%2Fapache%2Fhttpd.git Fold in the CAN-2003-0542 regex patch. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/APACHE_2_0_BRANCH@101555 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index a3517fa2e7d..03d30ee6619 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,10 @@ Changes with Apache 2.0.48 + *) SECURITY: CAN-2003-0542 (cve.mitre.org) + Fix buffer overflows in mod_alias and mod_rewrite which occurred if + one configured a regular expression with more than 9 captures. + [André Malo] + *) mod_include: fix segfault which occured if the filename was not set, for example, when processing some error conditions. PR 23836. [Brian Akins , André Malo] diff --git a/include/httpd.h b/include/httpd.h index 7951a8c0874..860a131f3f1 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -321,6 +321,9 @@ extern "C" { /** The size of the server's internal read-write buffers */ #define AP_IOBUFSIZE 8192 +/** The max number of regex captures that can be expanded by ap_pregsub */ +#define AP_MAX_REG_MATCH 10 + /** * APR_HAS_LARGE_FILES introduces the problem of spliting sendfile into * mutiple buckets, no greater than MAX(apr_size_t), and more granular diff --git a/modules/mappers/mod_alias.c b/modules/mappers/mod_alias.c index b5bea281c05..60bf7c79623 100644 --- a/modules/mappers/mod_alias.c +++ b/modules/mappers/mod_alias.c @@ -328,7 +328,7 @@ static char *try_alias_list(request_rec *r, apr_array_header_t *aliases, int doesc, int *status) { alias_entry *entries = (alias_entry *) aliases->elts; - regmatch_t regm[10]; + regmatch_t regm[AP_MAX_REG_MATCH]; char *found = NULL; int i; @@ -337,11 +337,10 @@ static char *try_alias_list(request_rec *r, apr_array_header_t *aliases, int l; if (p->regexp) { - if (!ap_regexec(p->regexp, r->uri, p->regexp->re_nsub + 1, regm, - 0)) { + if (!ap_regexec(p->regexp, r->uri, AP_MAX_REG_MATCH, regm, 0)) { if (p->real) { found = ap_pregsub(r->pool, p->real, r->uri, - p->regexp->re_nsub + 1, regm); + AP_MAX_REG_MATCH, regm); if (found && doesc) { apr_uri_t uri; apr_uri_parse(r->pool, found, &uri); diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index 63d17632b6e..ed1d2e4c839 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -1940,7 +1940,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p, const char *vary; char newuri[MAX_STRING_LEN]; regex_t *regexp; - regmatch_t regmatch[MAX_NMATCH]; + regmatch_t regmatch[AP_MAX_REG_MATCH]; backrefinfo *briRR = NULL; backrefinfo *briRC = NULL; int prefixstrip; @@ -1997,7 +1997,7 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p, rewritelog(r, 3, "[per-dir %s] applying pattern '%s' to uri '%s'", perdir, p->pattern, uri); } - rc = (ap_regexec(regexp, uri, regexp->re_nsub+1, regmatch, 0) == 0); + rc = (ap_regexec(regexp, uri, AP_MAX_REG_MATCH, regmatch, 0) == 0); if (! (( rc && !(p->flags & RULEFLAG_NOTMATCH)) || (!rc && (p->flags & RULEFLAG_NOTMATCH)) ) ) { return 0; @@ -2293,7 +2293,7 @@ static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p, char input[MAX_STRING_LEN]; apr_finfo_t sb; request_rec *rsub; - regmatch_t regmatch[MAX_NMATCH]; + regmatch_t regmatch[AP_MAX_REG_MATCH]; int rc; /* @@ -2398,8 +2398,7 @@ static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p, } else { /* it is really a regexp pattern, so apply it */ - rc = (ap_regexec(p->regexp, input, - p->regexp->re_nsub+1, regmatch,0) == 0); + rc = (ap_regexec(p->regexp, input, AP_MAX_REG_MATCH, regmatch,0) == 0); /* if it isn't a negated pattern and really matched we update the passed-through regex subst info structure */ @@ -2558,7 +2557,7 @@ static void do_expand(request_rec *r, char *input, char *buffer, int nbuf, bri = briRC; } /* see ap_pregsub() in src/main/util.c */ - if (bri && n <= bri->nsub + if (bri && n < AP_MAX_REG_MATCH && bri->regmatch[n].rm_eo > bri->regmatch[n].rm_so) { span = bri->regmatch[n].rm_eo - bri->regmatch[n].rm_so; if (span > space) { diff --git a/modules/mappers/mod_rewrite.h b/modules/mappers/mod_rewrite.h index b45c5f03b22..bbb5bc8cc87 100644 --- a/modules/mappers/mod_rewrite.h +++ b/modules/mappers/mod_rewrite.h @@ -210,8 +210,6 @@ /*** max cookie size in rfc 2109 ***/ #define MAX_COOKIE_LEN 4096 -#define MAX_NMATCH 10 - /* default maximum number of internal redirects */ #define REWRITE_REDIRECT_LIMIT 10 @@ -333,7 +331,7 @@ typedef struct cache { typedef struct backrefinfo { char *source; int nsub; - regmatch_t regmatch[10]; + regmatch_t regmatch[AP_MAX_REG_MATCH]; } backrefinfo; diff --git a/modules/proxy/proxy_ftp.c b/modules/proxy/proxy_ftp.c index c38773cb6b6..c6c1f65e25a 100644 --- a/modules/proxy/proxy_ftp.c +++ b/modules/proxy/proxy_ftp.c @@ -319,6 +319,10 @@ typedef struct { } state; } proxy_dir_ctx_t; +/* fallback regex for ls -s1; ($0..$2) == 3 */ +#define LS_REG_PATTERN "^ *([0-9]+) +([^ ]+)$" +#define LS_REG_MATCH 3 + apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, apr_bucket_brigade *in) { request_rec *r = f->r; @@ -462,10 +466,10 @@ apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, apr_bucket_brigade *in) int eos = 0; regex_t *re = NULL; - regmatch_t re_result[3]; + regmatch_t re_result[LS_REG_MATCH]; /* Compile the output format of "ls -s1" as a fallback for non-unix ftp listings */ - re = ap_pregcomp(p, "^ *([0-9]+) +([^ ]+)$", REG_EXTENDED); + re = ap_pregcomp(p, LS_REG_PATTERN, REG_EXTENDED); /* get a complete line */ /* if the buffer overruns - throw data away */ @@ -581,7 +585,7 @@ apr_status_t ap_proxy_send_dir_filter(ap_filter_t *f, apr_bucket_brigade *in) } } /* Try a fallback for listings in the format of "ls -s1" */ - else if (0 == ap_regexec(re, ctx->buffer, 3, re_result, 0)) { + else if (0 == ap_regexec(re, ctx->buffer, LS_REG_MATCH, re_result, 0)) { filename = apr_pstrndup(p, &ctx->buffer[re_result[2].rm_so], re_result[2].rm_eo - re_result[2].rm_so);