Ruediger Pluem wrote:

On 07/19/2009 01:12 AM, [email protected] wrote:
Author: niq
Date: Sat Jul 18 23:12:58 2009
New Revision: 795445

URL: http://svn.apache.org/viewvc?rev=795445&view=rev
Log:
Fix mod_include potential segfault checking backref from unmatched regexp
http://markmail.org/message/jlc7t5edsjujbe37
Patch by rpluem, lars, niq

Modified:
    httpd/httpd/trunk/include/ap_expr.h
    httpd/httpd/trunk/modules/filters/mod_include.c
    httpd/httpd/trunk/server/util_expr.c


Modified: httpd/httpd/trunk/modules/filters/mod_include.c
URL: 
http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/filters/mod_include.c?rev=795445&r1=795444&r2=795445&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/filters/mod_include.c (original)
+++ httpd/httpd/trunk/modules/filters/mod_include.c Sat Jul 18 23:12:58 2009
@@ -605,25 +605,30 @@
          * 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) {

IMHO this check should be the first (as in the old code) as it ensures that
idx is of correct range. So it should be moved before re->match[idx].rm_so == 
re->match[idx].rm_eo)

The problem with that is that re->nsub isn't the actual number of
matches, it's the maximum number we gave to regexec.  So that check
returns true even when idx indexes a non-match.

I'd say it would be better to set it to the number of actual matches
when we run regexec.  But I didn't want to think through the risk
of side-effects in a quick-fix scenario.

OTOH, bearing in mind the history of that code, it's never been
part of a public API in a stable release, so if we do create
side-effects, we're not at risk of breaking anything we shouldn't.
I guess we could reasonably hack it in trunk?

+            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);


As apr_pstrmemdup does return '\0' instead of NULL when re->match[idx].rm_so == 
re->match[idx].rm_eo
we change the behaviour by doing the re->match[idx].rm_so == 
re->match[idx].rm_eo check above.

Fair point.  Again, side-effects.  Let's reverse that change for 2.2
(and in trunk if you're unhappy with it).

--
Nick Kew

Reply via email to