mirror of
https://github.com/apache/httpd.git
synced 2025-08-10 02:02:49 +03:00
mod_proxy_http: make use of AP_GETLINE_NOSPC_EOL in ap_proxygetline().
Fixes response header thrown away after the previous one was considered too large and truncated. PR 62196. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1829573 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
3
CHANGES
3
CHANGES
@@ -1,6 +1,9 @@
|
|||||||
-*- coding: utf-8 -*-
|
-*- coding: utf-8 -*-
|
||||||
Changes with Apache 2.5.1
|
Changes with Apache 2.5.1
|
||||||
|
|
||||||
|
*) mod_proxy_http: Fix response header thrown away after the previous one
|
||||||
|
was considered too large and truncated. PR 62196. [Yann Ylavic]
|
||||||
|
|
||||||
*) core: Add and handle AP_GETLINE_NOSPC_EOL flag for ap_getline() family
|
*) core: Add and handle AP_GETLINE_NOSPC_EOL flag for ap_getline() family
|
||||||
of functions to consume the end of line when the buffer is exhausted.
|
of functions to consume the end of line when the buffer is exhausted.
|
||||||
PR 62198. [Yann Ylavic]
|
PR 62198. [Yann Ylavic]
|
||||||
|
@@ -28,12 +28,8 @@ static apr_status_t ap_proxy_http_cleanup(const char *scheme,
|
|||||||
request_rec *r,
|
request_rec *r,
|
||||||
proxy_conn_rec *backend);
|
proxy_conn_rec *backend);
|
||||||
|
|
||||||
static apr_status_t ap_proxygetline(apr_bucket_brigade *bb,
|
static apr_status_t ap_proxygetline(apr_bucket_brigade *bb, char *s, int n,
|
||||||
char *s,
|
request_rec *r, int flags, int *read);
|
||||||
int n,
|
|
||||||
request_rec *r,
|
|
||||||
int fold,
|
|
||||||
int *writen);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Canonicalise http-like URLs.
|
* Canonicalise http-like URLs.
|
||||||
@@ -1098,7 +1094,6 @@ static void ap_proxy_read_headers(request_rec *r, request_rec *rr,
|
|||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
char *value, *end;
|
char *value, *end;
|
||||||
char field[MAX_STRING_LEN];
|
|
||||||
int saw_headers = 0;
|
int saw_headers = 0;
|
||||||
void *sconf = r->server->module_config;
|
void *sconf = r->server->module_config;
|
||||||
proxy_server_conf *psc;
|
proxy_server_conf *psc;
|
||||||
@@ -1122,12 +1117,26 @@ static void ap_proxy_read_headers(request_rec *r, request_rec *rr,
|
|||||||
|
|
||||||
tmp_bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
tmp_bb = apr_brigade_create(r->pool, c->bucket_alloc);
|
||||||
while (1) {
|
while (1) {
|
||||||
rc = ap_proxygetline(tmp_bb, buffer, size, rr, 1, &len);
|
rc = ap_proxygetline(tmp_bb, buffer, size, rr,
|
||||||
|
AP_GETLINE_FOLD | AP_GETLINE_NOSPC_EOL, &len);
|
||||||
|
|
||||||
if (len <= 0)
|
if (len <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "%s", buffer);
|
if (APR_STATUS_IS_ENOSPC(rc)) {
|
||||||
|
/* The header could not fit in the provided buffer, warn.
|
||||||
|
* XXX: falls through with the truncated header, 5xx instead?
|
||||||
|
*/
|
||||||
|
int trunc = (len > 128 ? 128 : len) / 2;
|
||||||
|
ap_log_rerror(APLOG_MARK, APLOG_WARNING, rc, r, APLOGNO(10124)
|
||||||
|
"header size is over the limit allowed by "
|
||||||
|
"ResponseFieldSize (%d bytes). "
|
||||||
|
"Bad response header: '%.*s[...]%s'",
|
||||||
|
size, trunc, buffer, buffer + len - trunc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "%s", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */
|
if (!(value = strchr(buffer, ':'))) { /* Find the colon separator */
|
||||||
|
|
||||||
@@ -1195,28 +1204,6 @@ static void ap_proxy_read_headers(request_rec *r, request_rec *rr,
|
|||||||
*/
|
*/
|
||||||
process_proxy_header(r, dconf, buffer, value);
|
process_proxy_header(r, dconf, buffer, value);
|
||||||
saw_headers = 1;
|
saw_headers = 1;
|
||||||
|
|
||||||
/* The header could not fit in the provided buffer. */
|
|
||||||
if (rc == APR_ENOSPC) {
|
|
||||||
ap_log_rerror(APLOG_MARK, APLOG_WARNING, rc, r, APLOGNO(10124)
|
|
||||||
"header size is over the limit allowed by ResponseFieldSize (%d bytes). "
|
|
||||||
"Bad response header '%s': '%.*s'...",
|
|
||||||
size, buffer, 80, value);
|
|
||||||
|
|
||||||
/* XXX: We overran the limit we passed to ap_rgetline_core, but if the length
|
|
||||||
* exceeded the limit by a small amount, it may have already been consumed
|
|
||||||
* by apr_brigade_split_line called from the core input filter. If that
|
|
||||||
* happens, this loop will throw away the next full line (header) instead of
|
|
||||||
* the remainder of the current long header.
|
|
||||||
*/
|
|
||||||
while ((len = ap_getline(field, MAX_STRING_LEN, rr, 1))
|
|
||||||
>= MAX_STRING_LEN - 1) {
|
|
||||||
/* soak up the extra data */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len == 0) /* time to exit the larger loop as well */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1228,23 +1215,19 @@ static int addit_dammit(void *v, const char *key, const char *val)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static apr_status_t ap_proxygetline(apr_bucket_brigade *bb, char *s, int n,
|
||||||
apr_status_t ap_proxygetline(apr_bucket_brigade *bb, char *s, int n, request_rec *r,
|
request_rec *r, int flags, int *read)
|
||||||
int fold, int *writen)
|
|
||||||
{
|
{
|
||||||
char *tmp_s = s;
|
|
||||||
apr_status_t rv;
|
apr_status_t rv;
|
||||||
apr_size_t len;
|
apr_size_t len;
|
||||||
|
|
||||||
rv = ap_rgetline(&tmp_s, n, &len, r, fold, bb);
|
rv = ap_rgetline_core(&s, n, &len, r, flags, bb);
|
||||||
apr_brigade_cleanup(bb);
|
apr_brigade_cleanup(bb);
|
||||||
|
|
||||||
if (rv == APR_SUCCESS) {
|
if (rv == APR_SUCCESS || APR_STATUS_IS_ENOSPC(rv)) {
|
||||||
*writen = (int) len;
|
*read = (int)len;
|
||||||
} else if (APR_STATUS_IS_ENOSPC(rv)) {
|
|
||||||
*writen = n;
|
|
||||||
} else {
|
} else {
|
||||||
*writen = -1;
|
*read = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
Reference in New Issue
Block a user