diff options
author | Jeff Trawick <trawick@apache.org> | 2013-09-21 20:29:57 +0200 |
---|---|---|
committer | Jeff Trawick <trawick@apache.org> | 2013-09-21 20:29:57 +0200 |
commit | 6a64fadd63a6856871b7b7c859105d9c808e2a13 (patch) | |
tree | af2ff9fc6b72da9c47d76078292cd0d98378740f | |
parent | Updates. (diff) | |
download | apache2-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-- | CHANGES | 4 | ||||
-rw-r--r-- | docs/log-message-tags/next-number | 2 | ||||
-rw-r--r-- | modules/proxy/mod_proxy_fcgi.c | 102 |
3 files changed, 64 insertions, 44 deletions
@@ -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); |