]> granicus.if.org Git - apache/commitdiff
Limit ap_pregsub() to 64K, add ap_pregsub_ex() for longer strings and with
authorStefan Fritsch <sf@apache.org>
Tue, 25 Oct 2011 22:29:13 +0000 (22:29 +0000)
committerStefan Fritsch <sf@apache.org>
Tue, 25 Oct 2011 22:29:13 +0000 (22:29 +0000)
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

CHANGES
include/ap_mmn.h
include/httpd.h
include/util_varbuf.h
modules/filters/mod_substitute.c
server/util.c

diff --git a/CHANGES b/CHANGES
index 545bec39abbbd18fe5e7cd91e01556912c0a0bc7..c700897c8e0b5bff6176bca6fa30b2e6c574d028 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -12,6 +12,9 @@ Changes with Apache 2.3.15
      PR 51714. [Stefan Fritsch, Jim Jagielski, Ruediger Pluem, Eric Covener,
      <lowprio20 gmail.com>]
 
+  *) 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]
 
index 171655b79df6b162d920f3b970150649e6751a41..ce20e76ab5d9115f329eea42b0d9af675a95b3fa 100644 (file)
  *                         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 */
 
index f3fde289c44d625b112aded21dac1fcdecfd1598..f6b372eb539fa13e2edbee5a4a030a54aef07da4 100644 (file)
@@ -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.
index dc55e2c90cb2a7d0e96ca736f378f076ff9aabd0..64637f3b4c4d87e3ee3476e9d6a56634052d9856 100644 (file)
@@ -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
index 7b02926a06ebb11a00e90a5b3601332a216dda03..3a59caa99e2382e9e2eef75cffaaab05421c89bd 100644 (file)
@@ -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,
index cdeec894bf53446560556977992f360af5f35a1f..0f772e6305ca971ac2e69031c222a2242a16c976 100644 (file)
@@ -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, "