> -----Ursprüngliche Nachricht-----
> Von: Lars Eilebrecht [mailto:[email protected]]
> Gesendet: Freitag, 27. Februar 2009 12:54
> An: [email protected]
> 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