]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Bring some envvar flexibility from mod_authnz_fcgi to mod_proxy_fcgi:
authorJeff Trawick <trawick@apache.org>
Sat, 21 Sep 2013 18:29:57 +0000 (18:29 +0000)
committerJeff Trawick <trawick@apache.org>
Sat, 21 Sep 2013 18:29:57 +0000 (18:29 +0000)
mod_proxy_fcgi: Remove 64K limit on encoded length of all envvars.
An individual envvar with an encoded length of more than 16K will be
omitted.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1525276 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/log-message-tags/next-number
modules/proxy/mod_proxy_fcgi.c

diff --git a/CHANGES b/CHANGES
index bf35e116551417c600a8ccef80fca538b5124ff1..a0872d41ffc8554ff3408c020789e4135068b470 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,10 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
 
+  *) mod_proxy_fcgi: Remove 64K limit on encoded length of all envvars.
+     An individual envvar with an encoded length of more than 16K will be
+     omitted.  [Jeff Trawick]
+
   *) core: draft-ietf-httpbis-p1-messaging-23 corrections regarding
      TE/CL conflicts. [Yann Ylavic <ylavic.dev gmail com>, Jim Jagielski]
      
index 6a5bdca5ee17a7a64ae46e06a55e3293fb9f23be..099d024c1a15a4d51d5149d4155fe9a9e5a36117 100644 (file)
@@ -1 +1 @@
-2536
+2537
index 75d7ef53a19eaeaa9173cdd5d5892863f323960a..7b12dfe2cbf027c182751a7626b15a3407c9962f 100644 (file)
@@ -187,16 +187,17 @@ static apr_status_t send_begin_request(proxy_conn_rec *conn,
 }
 
 static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r,
+                                     apr_pool_t *temp_pool,
                                      apr_uint16_t request_id)
 {
     const apr_array_header_t *envarr;
+    const apr_table_entry_t *elts;
     struct iovec vec[2];
     ap_fcgi_header header;
     unsigned char farray[AP_FCGI_HEADER_LEN];
-    apr_size_t bodylen, envlen;
     char *body;
     apr_status_t rv;
-    apr_size_t avail_len, len;
+    apr_size_t avail_len, len, required_len;
     int next_elem, starting_elem;
 
     ap_add_common_vars(r);
@@ -204,8 +205,6 @@ static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r,
 
     /* XXX are there any FastCGI specific env vars we need to send? */
 
-    bodylen = envlen = 0;
-
     /* XXX mod_cgi/mod_cgid use ap_create_environment here, which fills in
      *     the TZ value specially.  We could use that, but it would mean
      *     parsing the key/value pairs back OUT of the allocated env array,
@@ -213,13 +212,12 @@ static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r,
      *     place, which would suck. */
 
     envarr = apr_table_elts(r->subprocess_env);
+    elts = (const apr_table_entry_t *) envarr->elts;
 
 #ifdef FCGI_DUMP_ENV_VARS
     {
-        const apr_table_entry_t *elts;
         int i;
         
-        elts = (const apr_table_entry_t *) envarr->elts;
         for (i = 0; i < envarr->nelts; ++i) {
             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01062)
                           "sending env var '%s' value '%s'",
@@ -228,42 +226,59 @@ static apr_status_t send_environment(proxy_conn_rec *conn, request_rec *r,
     }
 #endif
 
-    next_elem = 0; /* start encoding with first element */
-    starting_elem = next_elem;
-    avail_len = AP_FCGI_MAX_CONTENT_LEN;
-    bodylen = ap_fcgi_encoded_env_len(r->subprocess_env,
-                                      avail_len,
-                                      &next_elem);
-
-    if (next_elem < envarr->nelts) {
-        /* not everything encodable within limit specified in avail_len */
-        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01063)
-                      "truncating environment to %d bytes and %d elements",
-                      (int)bodylen, next_elem);
-    }
+    /* Send envvars over in as many FastCGI records as it takes, */
+    next_elem = 0; /* starting with the first one */
+
+    avail_len = 16 * 1024; /* our limit per record, which could have been up
+                            * to AP_FCGI_MAX_CONTENT_LEN
+                            */
+
+    while (next_elem < envarr->nelts) {
+        starting_elem = next_elem;
+        required_len = ap_fcgi_encoded_env_len(r->subprocess_env,
+                                               avail_len,
+                                               &next_elem);
+
+        if (!required_len) {
+            if (next_elem < envarr->nelts) {
+                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
+                              APLOGNO(02536) "couldn't encode envvar '%s' in %"
+                              APR_SIZE_T_FMT " bytes",
+                              elts[next_elem].key, avail_len);
+                /* skip this envvar and continue */
+                ++next_elem;
+                continue;
+            }
+            /* only an unused element at the end of the array */
+            break;
+        }
 
-    body = apr_pcalloc(r->pool, bodylen);
-    rv = ap_fcgi_encode_env(r, r->subprocess_env, body, bodylen,
-                            &starting_elem);
-    /* we pre-compute, so we can't run out of space */
-    ap_assert(rv == APR_SUCCESS);
-    /* compute and encode must be in sync */
-    ap_assert(starting_elem == next_elem);
+        body = apr_palloc(temp_pool, required_len);
+        rv = ap_fcgi_encode_env(r, r->subprocess_env, body, required_len,
+                                &starting_elem);
+        /* we pre-compute, so we can't run out of space */
+        ap_assert(rv == APR_SUCCESS);
+        /* compute and encode must be in sync */
+        ap_assert(starting_elem == next_elem);
 
-    ap_fcgi_fill_in_header(&header, AP_FCGI_PARAMS, request_id,
-                           (apr_uint16_t)bodylen, 0);
-    ap_fcgi_header_to_array(&header, farray);
+        ap_fcgi_fill_in_header(&header, AP_FCGI_PARAMS, request_id,
+                               (apr_uint16_t)required_len, 0);
+        ap_fcgi_header_to_array(&header, farray);
 
-    vec[0].iov_base = (void *)farray;
-    vec[0].iov_len = sizeof(farray);
-    vec[1].iov_base = body;
-    vec[1].iov_len = bodylen;
+        vec[0].iov_base = (void *)farray;
+        vec[0].iov_len = sizeof(farray);
+        vec[1].iov_base = body;
+        vec[1].iov_len = required_len;
 
-    rv = send_data(conn, vec, 2, &len, 1);
-    if (rv) {
-        return rv;
+        rv = send_data(conn, vec, 2, &len, 1);
+        apr_pool_clear(temp_pool);
+
+        if (rv) {
+            return rv;
+        }
     }
 
+    /* Envvars sent, so say we're done */
     ap_fcgi_fill_in_header(&header, AP_FCGI_PARAMS, request_id, 0, 0);
     ap_fcgi_header_to_array(&header, farray);
 
@@ -404,7 +419,8 @@ static void dump_header_to_log(request_rec *r, unsigned char fheader[],
 }
 
 static apr_status_t dispatch(proxy_conn_rec *conn, proxy_dir_conf *conf,
-                             request_rec *r, apr_uint16_t request_id)
+                             request_rec *r, apr_pool_t *setaside_pool,
+                             apr_uint16_t request_id)
 {
     apr_bucket_brigade *ib, *ob;
     int seen_end_of_headers = 0, done = 0;
@@ -416,10 +432,7 @@ static apr_status_t dispatch(proxy_conn_rec *conn, proxy_dir_conf *conf,
     unsigned char farray[AP_FCGI_HEADER_LEN];
     apr_pollfd_t pfd;
     int header_state = HDR_STATE_READING_HEADERS;
-    apr_pool_t *setaside_pool;
-
-    apr_pool_create(&setaside_pool, r->pool);
-
     pfd.desc_type = APR_POLL_SOCKET;
     pfd.desc.s = conn->sock;
     pfd.p = r->pool;
@@ -737,6 +750,7 @@ static int fcgi_do_request(apr_pool_t *p, request_rec *r,
      * keep things simple. */
     apr_uint16_t request_id = 1;
     apr_status_t rv;
+    apr_pool_t *temp_pool;
 
     /* Step 1: Send AP_FCGI_BEGIN_REQUEST */
     rv = send_begin_request(conn, request_id);
@@ -747,8 +761,10 @@ static int fcgi_do_request(apr_pool_t *p, request_rec *r,
         return HTTP_SERVICE_UNAVAILABLE;
     }
 
+    apr_pool_create(&temp_pool, r->pool);
+
     /* Step 2: Send Environment via FCGI_PARAMS */
-    rv = send_environment(conn, r, request_id);
+    rv = send_environment(conn, r, temp_pool, request_id);
     if (rv != APR_SUCCESS) {
         ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01074)
                       "Failed writing Environment to %s:", server_portstr);
@@ -757,7 +773,7 @@ static int fcgi_do_request(apr_pool_t *p, request_rec *r,
     }
 
     /* Step 3: Read records from the back end server and handle them. */
-    rv = dispatch(conn, conf, r, request_id);
+    rv = dispatch(conn, conf, r, temp_pool, request_id);
     if (rv != APR_SUCCESS) {
         ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01075)
                       "Error dispatching request to %s:", server_portstr);