From: Nick Kew Date: Sat, 18 Jul 2009 23:12:58 +0000 (+0000) Subject: Fix mod_include potential segfault checking backref from unmatched regexp X-Git-Tag: 2.3.3~428 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9cd5afd69253006fa6c8919b3e9e813cf78691ec;p=apache Fix mod_include potential segfault checking backref from unmatched regexp http://markmail.org/message/jlc7t5edsjujbe37 Patch by rpluem, lars, niq git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@795445 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/include/ap_expr.h b/include/ap_expr.h index 2763ee23d7..2f27f0fe45 100644 --- a/include/ap_expr.h +++ b/include/ap_expr.h @@ -73,6 +73,7 @@ typedef struct { const char *rexp; apr_size_t nsub; ap_regmatch_t match[AP_MAX_REG_MATCH]; + int have_match; } backref_t; typedef const char *(*string_func_t)(request_rec*, const char*); diff --git a/modules/filters/mod_include.c b/modules/filters/mod_include.c index 63637e3596..279322ed08 100644 --- a/modules/filters/mod_include.c +++ b/modules/filters/mod_include.c @@ -605,25 +605,30 @@ static const char *get_include_var(const char *var, include_ctx_t *ctx) * The choice of returning NULL strings on not-found, * v.s. empty strings on an empty match is deliberate. */ - if (!re) { + if (!re || !re->have_match) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "regex capture $%" APR_SIZE_T_FMT " refers to no regex in %s", idx, r->filename); return NULL; } - else { - 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", - idx, re->rexp, r->filename); - return NULL; - } - - if (re->match[idx].rm_so < 0 || re->match[idx].rm_eo < 0) { - return NULL; - } + else if (re->match[idx]rm_so == re->match[idx].rm_eo) { + return NULL; + } + else if (re->match[idx].rm_so < 0 || re->match[idx].rm_eo < 0) { + /* I don't think this can happen if have_match is true. + * But let's not risk a regression by dropping this + */ + return NULL; + } + else 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", + idx, re->rexp, r->filename); + return NULL; + } + else { val = apr_pstrmemdup(ctx->dpool, re->source + re->match[idx].rm_so, re->match[idx].rm_eo - re->match[idx].rm_so); } diff --git a/server/util_expr.c b/server/util_expr.c index 23c5750eaa..2a363ccd3a 100644 --- a/server/util_expr.c +++ b/server/util_expr.c @@ -265,7 +265,6 @@ static APR_INLINE int re_check(request_rec *r, const char *string, { ap_regex_t *compiled; backref_t *re = reptr ? *reptr : NULL; - int rc; compiled = ap_pregcomp(r->pool, rexp, AP_REG_EXTENDED); if (!compiled) { @@ -284,10 +283,11 @@ static APR_INLINE int re_check(request_rec *r, const char *string, re->source = apr_pstrdup(r->pool, string); re->rexp = apr_pstrdup(r->pool, rexp); re->nsub = compiled->re_nsub; - rc = !ap_regexec(compiled, string, AP_MAX_REG_MATCH, re->match, 0); + re->have_match = !ap_regexec(compiled, string, AP_MAX_REG_MATCH, + re->match, 0); ap_pregfree(r->pool, compiled); - return rc; + return re->have_match; } static int get_ptoken(apr_pool_t *pool, const char **parse, token_t *token,