]> granicus.if.org Git - apache/commitdiff
Fix mod_include potential segfault checking backref from unmatched regexp
authorNick Kew <niq@apache.org>
Sat, 18 Jul 2009 23:12:58 +0000 (23:12 +0000)
committerNick Kew <niq@apache.org>
Sat, 18 Jul 2009 23:12:58 +0000 (23:12 +0000)
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

include/ap_expr.h
modules/filters/mod_include.c
server/util_expr.c

index 2763ee23d700fb77a5e7e71833ae3f0c94152178..2f27f0fe458983ec990413fc897d9626d673cf4a 100644 (file)
@@ -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*);
index 63637e35961897b9b6106b5e3553d15dc0a60ea3..279322ed087fe566463617993dd510380a2b583a 100644 (file)
@@ -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);
         }
index 23c5750eaa3edccf4f852d23efe4eb6f3922b812..2a363ccd3a17c94939c874948cdb49b26900c558 100644 (file)
@@ -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,