From: Sander Striker Date: Fri, 24 Oct 2003 16:20:28 +0000 (+0000) Subject: Fold in the CAN-2003-0542 regex patch. X-Git-Tag: pre_ajp_proxy~1098 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=67a3a718776eaab2699f55e61a3472af04a7b751;p=thirdparty%2Fapache%2Fhttpd.git Fold in the CAN-2003-0542 regex patch. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@101556 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 2909ba6502d..6017250e039 100644 --- a/CHANGES +++ b/CHANGES @@ -210,6 +210,11 @@ Changes with Apache 2.1.0-dev 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 4f43931b3c0..7512e93ba6b 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -316,6 +316,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/filters/mod_include.c b/modules/filters/mod_include.c index f9551c07980..61706956070 100644 --- a/modules/filters/mod_include.c +++ b/modules/filters/mod_include.c @@ -201,13 +201,11 @@ typedef struct arg_item { apr_size_t value_len; } arg_item_t; -#define MAX_NMATCH 10 - typedef struct { const char *source; const char *rexp; apr_size_t nsub; - regmatch_t match[MAX_NMATCH]; + regmatch_t match[AP_MAX_REG_MATCH]; } backref_t; typedef struct { @@ -712,7 +710,7 @@ static const char *get_include_var(const char *var, include_ctx_t *ctx) return NULL; } else { - if (re->nsub < idx) { + if (re->nsub < idx || idx >= AP_MAX_REG_MATCH) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "regex capture $%" APR_SIZE_T_FMT " is out of range (last regex was: '%s') in %s", @@ -987,7 +985,7 @@ static APR_INLINE int re_check(include_ctx_t *ctx, const char *string, re->source = apr_pstrdup(ctx->pool, string); re->rexp = apr_pstrdup(ctx->pool, rexp); re->nsub = compiled->re_nsub; - rc = !ap_regexec(compiled, string, MAX_NMATCH, re->match, 0); + rc = !ap_regexec(compiled, string, AP_MAX_REG_MATCH, re->match, 0); ap_pregfree(ctx->dpool, compiled); return rc; diff --git a/modules/mappers/mod_alias.c b/modules/mappers/mod_alias.c index 9ceb4ad02f8..1068f82dbc8 100644 --- a/modules/mappers/mod_alias.c +++ b/modules/mappers/mod_alias.c @@ -354,7 +354,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; @@ -363,11 +363,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 5ccee38c5bb..e308c259268 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -214,9 +214,6 @@ /* XXX: not used at all. We should do a check somewhere and/or cut the cookie */ #define MAX_COOKIE_LEN 4096 -/* max number of regex captures */ -#define MAX_NMATCH 10 - /* default maximum number of internal redirects */ #define REWRITE_REDIRECT_LIMIT 10 @@ -368,7 +365,7 @@ typedef struct { typedef struct backrefinfo { char *source; int nsub; - regmatch_t regmatch[10]; + regmatch_t regmatch[AP_MAX_REG_MATCH]; } backrefinfo; /* single linked list used for @@ -2152,7 +2149,7 @@ static char *do_expand(char *input, rewrite_ctx *ctx) backrefinfo *bri = (*p == '$') ? &ctx->briRR : &ctx->briRC; /* see ap_pregsub() in server/util.c */ - if (bri->source && n <= bri->nsub + if (bri->source && 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; @@ -3356,7 +3353,7 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx) char *input = do_expand(p->input, ctx); apr_finfo_t sb; request_rec *rsub, *r = ctx->r; - regmatch_t regmatch[MAX_NMATCH]; + regmatch_t regmatch[AP_MAX_REG_MATCH]; int rc = 0; switch (p->ptype) { @@ -3437,7 +3434,7 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx) default: /* it is really a regexp pattern, so apply it */ - rc = !ap_regexec(p->regexp, input, p->regexp->re_nsub+1, regmatch, 0); + rc = !ap_regexec(p->regexp, input, AP_MAX_REG_MATCH, regmatch, 0); /* update briRC backref info */ if (rc && !(p->flags & CONDFLAG_NOTMATCH)) { @@ -3466,7 +3463,7 @@ static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx) */ static int apply_rewrite_rule(rewriterule_entry *p, rewrite_ctx *ctx) { - regmatch_t regmatch[MAX_NMATCH]; + regmatch_t regmatch[AP_MAX_REG_MATCH]; apr_array_header_t *rewriteconds; rewritecond_entry *conds; int i, rc; @@ -3505,7 +3502,7 @@ static int apply_rewrite_rule(rewriterule_entry *p, rewrite_ctx *ctx) rewritelog((r, 3, ctx->perdir, "applying pattern '%s' to uri '%s'", p->pattern, ctx->uri)); - rc = !ap_regexec(p->regexp, ctx->uri, p->regexp->re_nsub+1, regmatch, 0); + rc = !ap_regexec(p->regexp, ctx->uri, AP_MAX_REG_MATCH, regmatch, 0); if (! (( rc && !(p->flags & RULEFLAG_NOTMATCH)) || (!rc && (p->flags & RULEFLAG_NOTMATCH)) ) ) { return 0; diff --git a/modules/metadata/mod_setenvif.c b/modules/metadata/mod_setenvif.c index 6b2d0339676..5a1268eb0f4 100644 --- a/modules/metadata/mod_setenvif.c +++ b/modules/metadata/mod_setenvif.c @@ -489,7 +489,7 @@ static int match_headers(request_rec *r) apr_size_t val_len = 0; int i, j; char *last_name; - regmatch_t regm[10]; + regmatch_t regm[AP_MAX_REG_MATCH]; if (!ap_get_module_config(r->request_config, &setenvif_module)) { ap_set_module_config(r->request_config, &setenvif_module, @@ -577,8 +577,8 @@ static int match_headers(request_rec *r) } if ((b->pattern && apr_strmatch(b->pattern, val, val_len)) || - (!b->pattern && !ap_regexec(b->preg, val, b->preg->re_nsub + 1, - regm, 0))) { + (!b->pattern && !ap_regexec(b->preg, val, AP_MAX_REG_MATCH, regm, + 0))) { const apr_array_header_t *arr = apr_table_elts(b->features); elts = (const apr_table_entry_t *) arr->elts; @@ -589,7 +589,7 @@ static int match_headers(request_rec *r) else { if (!b->pattern) { char *replaced = ap_pregsub(r->pool, elts[j].val, val, - b->preg->re_nsub + 1, regm); + AP_MAX_REG_MATCH, regm); if (replaced) { apr_table_setn(r->subprocess_env, elts[j].key, replaced); diff --git a/modules/proxy/proxy_ftp.c b/modules/proxy/proxy_ftp.c index 8df516a6805..bd9d9c07b11 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);