2.2.x patch: trunk patch works modulo CHANGES
+1: trawick, wrowe, rjung
- * core: Limit ap_pregsub() to 64MB, add ap_pregsub_ex() for longer strings.
- The default limit can be adjusted at compile time using AP_PREGSUB_MAXLEN.
- mod_setenvif: Log error on substitution overflow.
-
- IMPORTANT: This could break existing configurations which rely on
- substitutions > 64MB. Those sites need to rebuild with an
- override of AP_PREGSUB_MAXLEN.
- 2.4.x has a much smaller limit on ap_pregsub() because that change
- was introduced with the new release.
-
- trunk patch:
- util.c: too many to list, as it is tied up in other added features and follow-
- up fixes; I started with 2.4.x HEAD and backed out some semantic changes
- in the code of interest
- mod_setenvif.c: http://svn.apache.org/viewvc?view=revision&revision=1198966
- 2.2.x patch: http://people.apache.org/~trawick/ap_pregsub_ex_22x-2.txt
- +1: trawick, wrowe, covener
-
-
-
PATCHES PROPOSED TO BACKPORT FROM TRUNK:
[ New proposals should be added at the end of the list ]
* 20051115.29 (2.2.21) add max_ranges to core_dir_config
* 20051115.30 (2.2.21) add ap_set_accept_ranges()
* 20051115.31 (2.2.23) Add forcerecovery to proxy_balancer_shared struct
- # 20051115.32 (2.2.24) Add ap_get_exec_line
+ * 20051115.32 (2.2.24) Add ap_get_exec_line
+ * 20051115.33 (2.2.24) Add ap_pregsub_ex()
*/
#define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20051115
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 32 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 33 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
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, 0 for unlimited
+ * @return APR_SUCCESS if successful, APR_ENOMEM or other error code otherwise.
+ */
+AP_DECLARE(apr_status_t) ap_pregsub_ex(apr_pool_t *p, char **result,
+ const char *input, const char *source,
+ apr_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.
apr_table_setn(r->subprocess_env, elts[j].key,
replaced);
}
+ else {
+ ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
+ "Regular expression replacement "
+ "failed for '%s', value too long?",
+ elts[j].key);
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
}
else {
apr_table_setn(r->subprocess_env, elts[j].key,
* AT&T V8 regexp package.
*/
-AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, 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,
+ const char *input,
+ const char *source, apr_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;
- apr_size_t len;
+ apr_size_t no;
+ apr_size_t len = 0;
- if (!source)
- return NULL;
- if (!nmatch)
- return apr_pstrdup(p, src);
+ AP_DEBUG_ASSERT(result && p);
+ if (!source || nmatch>AP_MAX_REG_MATCH)
+ return APR_EINVAL;
+ if (!nmatch) {
+ len = strlen(src);
+ if (maxlen > 0 && len >= maxlen)
+ return APR_ENOMEM;
+ *result = apr_pstrmemdup(p, src, len);
+ return APR_SUCCESS;
+ }
/* First pass, find the size */
-
- len = 0;
-
while ((c = *src++) != '\0') {
if (c == '&')
no = 0;
else if (c == '$' && apr_isdigit(*src))
no = *src++ - '0';
else
- no = 10;
+ no = AP_MAX_REG_MATCH;
- if (no > 9) { /* Ordinary character. */
+ if (no >= AP_MAX_REG_MATCH) { /* Ordinary character. */
if (c == '\\' && (*src == '$' || *src == '&'))
src++;
len++;
if (UTIL_SIZE_MAX - len <= pmatch[no].rm_eo - pmatch[no].rm_so) {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL,
"integer overflow or out of memory condition." );
- return NULL;
+ return APR_ENOMEM;
}
len += pmatch[no].rm_eo - pmatch[no].rm_so;
}
}
- dest = dst = apr_pcalloc(p, len + 1);
+ if (len >= maxlen && maxlen > 0)
+ return APR_ENOMEM;
+
+ *result = dst = apr_palloc(p, len + 1);
/* Now actually fill in the string */
else if (c == '$' && apr_isdigit(*src))
no = *src++ - '0';
else
- no = 10;
+ no = AP_MAX_REG_MATCH;
- if (no > 9) { /* Ordinary character. */
+ if (no >= AP_MAX_REG_MATCH) { /* Ordinary character. */
if (c == '\\' && (*src == '$' || *src == '&'))
c = *src++;
*dst++ = c;
}
*dst = '\0';
- return dest;
+ return APR_SUCCESS;
+}
+
+#ifndef AP_PREGSUB_MAXLEN
+/* No API control so far in this released branch, so make it large */
+#define AP_PREGSUB_MAXLEN (64 * 1024 * 1024)
+#endif
+AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input,
+ const char *source, size_t nmatch,
+ ap_regmatch_t pmatch[])
+{
+ char *result;
+ apr_status_t rc = regsub_core(p, &result, 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,
+ apr_size_t nmatch, ap_regmatch_t pmatch[],
+ apr_size_t maxlen)
+{
+ apr_status_t rc = regsub_core(p, result, input, source, nmatch,
+ pmatch, maxlen);
+ if (rc != APR_SUCCESS)
+ *result = NULL;
+ return rc;
}
/*