summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Trawick <trawick@apache.org>2013-09-21 20:29:57 +0200
committerJeff Trawick <trawick@apache.org>2013-09-21 20:29:57 +0200
commit6a64fadd63a6856871b7b7c859105d9c808e2a13 (patch)
treeaf2ff9fc6b72da9c47d76078292cd0d98378740f
parentUpdates. (diff)
downloadapache2-6a64fadd63a6856871b7b7c859105d9c808e2a13.tar.xz
apache2-6a64fadd63a6856871b7b7c859105d9c808e2a13.zip
Bring some envvar flexibility from mod_authnz_fcgi to mod_proxy_fcgi:
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
-rw-r--r--CHANGES4
-rw-r--r--docs/log-message-tags/next-number2
-rw-r--r--modules/proxy/mod_proxy_fcgi.c102
3 files changed, 64 insertions, 44 deletions
diff --git a/CHANGES b/CHANGES
index bf35e11655..a0872d41ff 100644
--- 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]
diff --git a/docs/log-message-tags/next-number b/docs/log-message-tags/next-number
index 6a5bdca5ee..099d024c1a 100644
--- a/docs/log-message-tags/next-number
+++ b/docs/log-message-tags/next-number
@@ -1 +1 @@
-2536
+2537
diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c
index 75d7ef53a1..7b12dfe2cb 100644
--- a/modules/proxy/mod_proxy_fcgi.c
+++ b/modules/proxy/mod_proxy_fcgi.c
@@ -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);