From: Stefan Fritsch Date: Tue, 25 Oct 2011 22:29:13 +0000 (+0000) Subject: Limit ap_pregsub() to 64K, add ap_pregsub_ex() for longer strings and with X-Git-Tag: 2.3.15~85 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=04ca93ecfff9e24a8d491eaaefb3e466f234c17b;p=apache Limit ap_pregsub() to 64K, add ap_pregsub_ex() for longer strings and with better error reporting. Modify ap_varbuf_regsub() to be similar to ap_pregsub_ex(). git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1188950 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 545bec39ab..c700897c8e 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,9 @@ Changes with Apache 2.3.15 PR 51714. [Stefan Fritsch, Jim Jagielski, Ruediger Pluem, Eric Covener, ] + *) core: Limit ap_pregsub() to 64K, add ap_pregsub_ex() for longer strings. + [Stefan Fritsch] + *) mod_session_crypto: Refactor to support the new apr_crypto API. [Graham Leggett] diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 171655b79d..ce20e76ab5 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -360,12 +360,14 @@ * add ap_unixd_config.group_name * 20111014.0 (2.3.15-dev) Remove cookie_path_str and cookie_domain_str from * proxy_dir_conf + * 20111025.0 (2.3.15-dev) Add return value and maxlen to ap_varbuf_regsub(), + * add ap_pregsub_ex() */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ #ifndef MODULE_MAGIC_NUMBER_MAJOR -#define MODULE_MAGIC_NUMBER_MAJOR 20111014 +#define MODULE_MAGIC_NUMBER_MAJOR 20111025 #endif #define MODULE_MAGIC_NUMBER_MINOR 0 /* 0...n */ diff --git a/include/httpd.h b/include/httpd.h index f3fde289c4..f6b372eb53 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -1775,7 +1775,8 @@ AP_DECLARE(void) ap_pregfree(apr_pool_t *p, ap_regex_t *reg); /** * After performing a successful regex match, you may use this function to * perform a series of string substitutions based on subexpressions that were - * matched during the call to ap_regexec + * matched during the call to ap_regexec. This function is limited to + * result strings of 64K. Consider using ap_pregsub_ex() instead. * @param p The pool to allocate from * @param input An arbitrary string containing $1 through $9. These are * replaced with the corresponding matched sub-expressions @@ -1787,6 +1788,25 @@ AP_DECLARE(void) ap_pregfree(apr_pool_t *p, ap_regex_t *reg); AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input, const char *source, size_t nmatch, ap_regmatch_t pmatch[]); +/** + * After performing a successful regex match, you may use this function to + * perform a series of string substitutions based on subexpressions that were + * matched during the call to ap_regexec + * @param p The pool to allocate from + * @param result where to store the result, will be set to NULL on error + * @param input An arbitrary string containing $1 through $9. These are + * replaced with the corresponding matched sub-expressions + * @param source The string that was originally matched to the regex + * @param nmatch the nmatch returned from ap_pregex + * @param pmatch the pmatch array returned from ap_pregex + * @param maxlen the maximum string length to return + * @return The substituted string, or NULL on error + */ +AP_DECLARE(apr_status_t) ap_pregsub_ex(apr_pool_t *p, char **result, + const char *input, const char *source, + size_t nmatch, ap_regmatch_t pmatch[], + apr_size_t maxlen); + /** * We want to downcase the type/subtype for comparison purposes * but nothing else because ;parameter=foo values are case sensitive. diff --git a/include/util_varbuf.h b/include/util_varbuf.h index dc55e2c90c..64637f3b4c 100644 --- a/include/util_varbuf.h +++ b/include/util_varbuf.h @@ -135,13 +135,17 @@ AP_DECLARE(char *) ap_varbuf_pdup(apr_pool_t *p, struct ap_varbuf *vb, * @param source The string that was originally matched to the regex * @param nmatch the nmatch returned from ap_pregex * @param pmatch the pmatch array returned from ap_pregex + * @param maxlen the maximum string length to append to vb + * @return APR_SUCCESS if successful * @note Just like ap_pregsub(), this function does not copy the part of * *source before the matching part (i.e. the first pmatch[0].rm_so * characters). */ -AP_DECLARE(void) ap_varbuf_regsub(struct ap_varbuf *vb, const char *input, - const char *source, size_t nmatch, - ap_regmatch_t pmatch[]); +AP_DECLARE(apr_status_t) ap_varbuf_regsub(struct ap_varbuf *vb, + const char *input, + const char *source, size_t nmatch, + ap_regmatch_t pmatch[], + apr_size_t maxlen); /** Read a line from an ap_configfile_t into an ap_varbuf. * @param vb pointer to the ap_varbuf struct diff --git a/modules/filters/mod_substitute.c b/modules/filters/mod_substitute.c index 7b02926a06..3a59caa99e 100644 --- a/modules/filters/mod_substitute.c +++ b/modules/filters/mod_substitute.c @@ -196,7 +196,8 @@ static void do_pattmatch(ap_filter_t *f, apr_bucket *inb, ap_varbuf_strmemcat(&vb, pos, regm[0].rm_so); /* add replacement string */ ap_varbuf_regsub(&vb, script->replacement, pos, - AP_MAX_REG_MATCH, regm); + AP_MAX_REG_MATCH, regm, + APR_SIZE_MAX); } else { repl = ap_pregsub(pool, script->replacement, pos, diff --git a/server/util.c b/server/util.c index cdeec894bf..0f772e6305 100644 --- a/server/util.c +++ b/server/util.c @@ -370,32 +370,35 @@ AP_DECLARE(const char *) ap_stripprefix(const char *bigstring, * AT&T V8 regexp package. */ -static char *regsub_core(apr_pool_t *p, struct ap_varbuf *vb, - const char *input, const char *source, - size_t nmatch, ap_regmatch_t pmatch[]) +static apr_status_t regsub_core(apr_pool_t *p, char **result, + struct ap_varbuf *vb, const char *input, + const char *source, size_t nmatch, + ap_regmatch_t pmatch[], apr_size_t maxlen) { const char *src = input; - char *dest, *dst; + char *dst; char c; size_t no; - int len; + apr_size_t len = 0; + AP_DEBUG_ASSERT((result && p && !vb) || (vb && !p && !result)); if (!source) - return NULL; + return APR_EINVAL; if (!nmatch || nmatch>AP_MAX_REG_MATCH) { + len = strlen(src); + if (maxlen > 0 && len > maxlen) + return APR_ENOMEM; if (!vb) { - return apr_pstrdup(p, src); + *result = apr_pstrmemdup(p, src, len); + return APR_SUCCESS; } else { - ap_varbuf_strcat(vb, src); - return NULL; + ap_varbuf_strmemcat(vb, src, len); + return APR_SUCCESS; } } /* First pass, find the size */ - - len = 0; - while ((c = *src++) != '\0') { if (c == '$' && apr_isdigit(*src)) no = *src++ - '0'; @@ -413,14 +416,17 @@ static char *regsub_core(apr_pool_t *p, struct ap_varbuf *vb, } + if (len > maxlen && maxlen > 0) + return APR_ENOMEM; + if (!vb) { - dest = dst = apr_pcalloc(p, len + 1); + *result = dst = apr_pcalloc(p, len + 1); } else { if (vb->buf && vb->strlen == AP_VARBUF_UNKNOWN) vb->strlen = strlen(vb->buf); ap_varbuf_grow(vb, vb->strlen + len); - dest = dst = vb->buf + vb->strlen; + dst = vb->buf + vb->strlen; vb->strlen += len; } @@ -450,14 +456,34 @@ static char *regsub_core(apr_pool_t *p, struct ap_varbuf *vb, } *dst = '\0'; - return dest; + return APR_SUCCESS; } +#ifndef AP_PREGSUB_MAXLEN +#define AP_PREGSUB_MAXLEN 65536 +#endif AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input, const char *source, size_t nmatch, ap_regmatch_t pmatch[]) { - return regsub_core(p, NULL, input, source, nmatch, pmatch); + char *result; + apr_status_t rc = regsub_core(p, &result, NULL, input, source, nmatch, + pmatch, AP_PREGSUB_MAXLEN); + if (rc != APR_SUCCESS) + result = NULL; + return result; +} + +AP_DECLARE(apr_status_t) ap_pregsub_ex(apr_pool_t *p, char **result, + const char *input, const char *source, + size_t nmatch, ap_regmatch_t pmatch[], + apr_size_t maxlen) +{ + apr_status_t rc = regsub_core(p, result, NULL, input, source, nmatch, + pmatch, maxlen); + if (rc != APR_SUCCESS) + *result = NULL; + return rc; } /* @@ -2647,11 +2673,13 @@ AP_DECLARE(char *) ap_varbuf_pdup(apr_pool_t *p, struct ap_varbuf *buf, return ""; } -AP_DECLARE(void) ap_varbuf_regsub(struct ap_varbuf *vb, const char *input, - const char *source, size_t nmatch, - ap_regmatch_t pmatch[]) +AP_DECLARE(apr_status_t) ap_varbuf_regsub(struct ap_varbuf *vb, + const char *input, + const char *source, size_t nmatch, + ap_regmatch_t pmatch[], + apr_size_t maxlen) { - regsub_core(NULL, vb, input, source, nmatch, pmatch); + return regsub_core(NULL, NULL, vb, input, source, nmatch, pmatch, maxlen); } static const char * const oom_message = "[crit] Memory allocation failed, "