]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
* core: Limit ap_pregsub() to 64MB, add ap_pregsub_ex() for longer strings.
authorEric Covener <covener@apache.org>
Thu, 27 Jun 2013 16:29:37 +0000 (16:29 +0000)
committerEric Covener <covener@apache.org>
Thu, 27 Jun 2013 16:29:37 +0000 (16:29 +0000)
    The default limit can be adjusted at compile time using AP_PREGSUB_MAXLEN.
    mod_setenvif: Log error on substitution overflow.

Submitted by: trawick
Reviewed by: trawic, wrowe, covener

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@1497429 13f79535-47bb-0310-9956-ffa450edef68

STATUS
include/ap_mmn.h
include/httpd.h
modules/metadata/mod_setenvif.c
server/util.c

diff --git a/STATUS b/STATUS
index b4c7a18483bdbd1f28742e4c1f4da240ec475e5b..5198c16dacf82c55eb050b75bbd3937b088ec766 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -141,26 +141,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
     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 ]
 
index 1b2cfa02a621aef5e8f1bbb0d9dac5a4b35547e4..4a48c3e0dbb5c43b7c4b9dd2cc496a0f44a9869e 100644 (file)
  * 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
index 5bf2cfe71357010578f1fee20a92c79ca9901150..f353d9ff7baae17c438cd6d5755fbba3d681a0af 100644 (file)
@@ -1700,6 +1700,26 @@ 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, 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.
index 2c84cedefc973d1632ab6fe3a87fa35b2e808bc7..6848c9ae7c5aa1286b3bd00ad658e3baf2a1f790 100644 (file)
@@ -555,6 +555,13 @@ static int match_headers(request_rec *r)
                             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,
index b334c964537962431b60c8e4b2475f5a7cbb615b..f1fb2550f15e70ada26b5b0743e91366ef4ab690 100644 (file)
@@ -360,34 +360,38 @@ AP_DECLARE(const char *) ap_stripprefix(const char *bigstring,
  * 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++;
@@ -396,14 +400,17 @@ AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input,
             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 */
 
@@ -415,9 +422,9 @@ AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input,
         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;
@@ -431,7 +438,35 @@ AP_DECLARE(char *) ap_pregsub(apr_pool_t *p, const char *input,
     }
     *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;
 }
 
 /*