> -----Ursprüngliche Nachricht-----
> Von: Lars Eilebrecht [mailto:l...@eilebrecht.net] 
> Gesendet: Freitag, 27. Februar 2009 12:54
> An: dev@httpd.apache.org
> Betreff: Re: regex-related segfault in mod_include
> 
> Ruediger Pluem wrote:
> 
> > What are the values of
> > 
> > idx
> > re->match[idx].rm_so
> > re->match[idx].rm_eo
> > re->source
> > 
> > and what is the string re->source is pointing to when the 
> crash happens?
> 
> idx is 1 and re->source points to an empty string which is fine.
> However, re->match[idx].rm_so and re->match[idx].rm_eo are 
> random numbers,
> i.e., a garbage value (I guess they should be 0 if there was 
> no match?).

IMHO they should be -1. 

> Thus the argument "re->source + re->match[idx].rm_so" ends up 
> pointing to
> an out of band location (and a memcpy() for that location results in
> the segfault).
> 
> I just don't really get why this happens in some cases (like 1 out of
> 10 requests).
> 
> BTW, I can reproduce this on Solaris and Linux (worker and prefork)
> with 2.2.11. With 2.0 this works fine.

We use different PCRE versions in both (and maybe mod_include changed too).
I suspect that if ap_regexec in re_check does not detect a match 
re->match[idx].rm_so is not setup correctly (maybe this changed between the
different PCRE versions) and as we do not check in get_include_var if we had
a match at all we fall over. So we should either memorize in the re struct
if we matched or not by an additional flag, so something like (untested)

Index: mod_include.c
===================================================================
--- mod_include.c       (revision 748051)
+++ mod_include.c       (working copy)
@@ -158,6 +158,7 @@
     const char *rexp;
     apr_size_t  nsub;
     ap_regmatch_t match[AP_MAX_REG_MATCH];
+    int         matched;
 } backref_t;

 typedef struct {
@@ -672,7 +673,8 @@
                 return NULL;
             }

-            if (re->match[idx].rm_so < 0 || re->match[idx].rm_eo < 0) {
+            if (re->match[idx].rm_so < 0 || re->match[idx].rm_eo < 0
+                || !re->matched) {
                 return NULL;
             }

@@ -923,7 +925,6 @@
 {
     ap_regex_t *compiled;
     backref_t *re = ctx->intern->re;
-    int rc;

     compiled = ap_pregcomp(ctx->dpool, rexp, AP_REG_EXTENDED);
     if (!compiled) {
@@ -939,10 +940,10 @@
     re->source = apr_pstrdup(ctx->pool, string);
     re->rexp = apr_pstrdup(ctx->pool, rexp);
     re->nsub = compiled->re_nsub;
-    rc = !ap_regexec(compiled, string, AP_MAX_REG_MATCH, re->match, 0);
+    re->matched = !ap_regexec(compiled, string, AP_MAX_REG_MATCH, re->match, 
0);

     ap_pregfree(ctx->dpool, compiled);
-    return rc;
+    return re->matched;
 }

 static int get_ptoken(include_ctx_t *ctx, const char **parse, token_t *token, 
token_t *previous)


or we should initialize the match array correctly:

Index: mod_include.c
===================================================================
--- mod_include.c       (revision 748051)
+++ mod_include.c       (working copy)
@@ -924,6 +924,7 @@
     ap_regex_t *compiled;
     backref_t *re = ctx->intern->re;
     int rc;
+    int i;

     compiled = ap_pregcomp(ctx->dpool, rexp, AP_REG_EXTENDED);
     if (!compiled) {
@@ -939,6 +940,10 @@
     re->source = apr_pstrdup(ctx->pool, string);
     re->rexp = apr_pstrdup(ctx->pool, rexp);
     re->nsub = compiled->re_nsub;
+    for (i = 0; i < AP_MAX_REG_MATCH; i++) {
+        re->match[i].rm_so = -1;
+        re->match[i].rm_eo = -1;
+    }
     rc = !ap_regexec(compiled, string, AP_MAX_REG_MATCH, re->match, 0);

     ap_pregfree(ctx->dpool, compiled);


Regards

Rüdiger

Reply via email to