You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by mi...@apache.org on 2020/07/08 11:09:13 UTC
svn commit: r1879639 - in /httpd/httpd/branches/2.4.x: ./ include/
modules/cache/ modules/dav/main/ modules/filters/ modules/http/
modules/mappers/ modules/proxy/ server/
Author: minfrin
Date: Wed Jul 8 11:09:13 2020
New Revision: 1879639
URL: http://svn.apache.org/viewvc?rev=1879639&view=rev
Log:
*) strict content-length parsing
trunk patch http://svn.apache.org/r1877954
http://svn.apache.org/r1877955
http://svn.apache.org/r1879369
http://svn.apache.org/r1879373
2.4.x patch: http://people.apache.org/~ylavic/patches/httpd-2.4.x-ap_parse_strict_length.patch
+1: ylavic, minfrin, jim
Modified:
httpd/httpd/branches/2.4.x/CHANGES
httpd/httpd/branches/2.4.x/STATUS
httpd/httpd/branches/2.4.x/include/ap_mmn.h
httpd/httpd/branches/2.4.x/include/httpd.h
httpd/httpd/branches/2.4.x/modules/cache/mod_cache.c
httpd/httpd/branches/2.4.x/modules/cache/mod_cache_disk.c
httpd/httpd/branches/2.4.x/modules/cache/mod_cache_socache.c
httpd/httpd/branches/2.4.x/modules/dav/main/mod_dav.c
httpd/httpd/branches/2.4.x/modules/filters/mod_data.c
httpd/httpd/branches/2.4.x/modules/filters/mod_reflector.c
httpd/httpd/branches/2.4.x/modules/filters/mod_request.c
httpd/httpd/branches/2.4.x/modules/http/byterange_filter.c
httpd/httpd/branches/2.4.x/modules/http/http_filters.c
httpd/httpd/branches/2.4.x/modules/mappers/mod_negotiation.c
httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.c
httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ajp.c
httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_http.c
httpd/httpd/branches/2.4.x/server/protocol.c
httpd/httpd/branches/2.4.x/server/util.c
Modified: httpd/httpd/branches/2.4.x/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/CHANGES?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/CHANGES [utf-8] (original)
+++ httpd/httpd/branches/2.4.x/CHANGES [utf-8] Wed Jul 8 11:09:13 2020
@@ -1,6 +1,9 @@
-*- coding: utf-8 -*-
Changes with Apache 2.4.44
+ *) Add support for strict content-length parsing through addition of
+ ap_parse_strict_length() [Yann Ylavic]
+
*) mod_proxy_fcgi: ProxyFCGISetEnvIf unsets variables when expression
evaluates to false. PR64365. [Michael König <mail ikoenig.net>]
Modified: httpd/httpd/branches/2.4.x/STATUS
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/STATUS?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/STATUS (original)
+++ httpd/httpd/branches/2.4.x/STATUS Wed Jul 8 11:09:13 2020
@@ -135,15 +135,6 @@ RELEASE SHOWSTOPPERS:
PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
[ start all new proposals below, under PATCHES PROPOSED. ]
- *) strict content-length parsing
- trunk patch http://svn.apache.org/r1877954
- http://svn.apache.org/r1877955
- http://svn.apache.org/r1879369
- http://svn.apache.org/r1879373
- 2.4.x patch: http://people.apache.org/~ylavic/patches/httpd-2.4.x-ap_parse_strict_length.patch
- +1: ylavic, minfrin, jim
- ylavic: the patch drops changes to apreq, which seems to not be in 2.4.
-
*) core: Drop an invalid Last-Modified header value coming
from a (F)CGI script instead of replacing it with Unix epoch.
Warn the users about Last-Modified header value replacements
Modified: httpd/httpd/branches/2.4.x/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/include/ap_mmn.h?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/include/ap_mmn.h (original)
+++ httpd/httpd/branches/2.4.x/include/ap_mmn.h Wed Jul 8 11:09:13 2020
@@ -534,6 +534,7 @@
* 20120211.90 (2.4.42-dev) AP_REG_DEFAULT macro in ap_regex.h
* 20120211.91 (2.4.42-dev) Add ap_is_chunked() in httpd.h
* 20120211.92 (2.4.42-dev) AP_REG_NO_DEFAULT macro in ap_regex.h
+ * 20120211.93 (2.4.44-dev) Add ap_parse_strict_length()
*/
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -541,7 +542,7 @@
#ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20120211
#endif
-#define MODULE_MAGIC_NUMBER_MINOR 92 /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 93 /* 0...n */
/**
* Determine if the server's current MODULE_MAGIC_NUMBER is at least a
Modified: httpd/httpd/branches/2.4.x/include/httpd.h
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/include/httpd.h?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/include/httpd.h (original)
+++ httpd/httpd/branches/2.4.x/include/httpd.h Wed Jul 8 11:09:13 2020
@@ -2053,6 +2053,15 @@ AP_DECLARE(char *) ap_append_pid(apr_poo
const char *delim);
/**
+ * Parse a length string with decimal characters only, no leading sign nor
+ * trailing character, like Content-Length or (Content-)Range headers.
+ * @param len The parsed length (apr_off_t)
+ * @param str The string to parse
+ * @return 1 (success), 0 (failure)
+ */
+AP_DECLARE(int) ap_parse_strict_length(apr_off_t *len, const char *str);
+
+/**
* Parse a given timeout parameter string into an apr_interval_time_t value.
* The unit of the time interval is given as postfix string to the numeric
* string. Currently the following units are understood:
Modified: httpd/httpd/branches/2.4.x/modules/cache/mod_cache.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/cache/mod_cache.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/cache/mod_cache.c (original)
+++ httpd/httpd/branches/2.4.x/modules/cache/mod_cache.c Wed Jul 8 11:09:13 2020
@@ -1229,6 +1229,16 @@ static apr_status_t cache_save_filter(ap
return APR_SUCCESS;
}
+ /* Set the content length if known.
+ */
+ cl = apr_table_get(r->err_headers_out, "Content-Length");
+ if (cl == NULL) {
+ cl = apr_table_get(r->headers_out, "Content-Length");
+ }
+ if (cl && !ap_parse_strict_length(&size, cl)) {
+ reason = "invalid content length";
+ }
+
if (reason) {
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00768)
"cache: %s not cached for request %s. Reason: %s",
@@ -1251,19 +1261,6 @@ static apr_status_t cache_save_filter(ap
/* Make it so that we don't execute this path again. */
cache->in_checked = 1;
- /* Set the content length if known.
- */
- cl = apr_table_get(r->err_headers_out, "Content-Length");
- if (cl == NULL) {
- cl = apr_table_get(r->headers_out, "Content-Length");
- }
- if (cl) {
- char *errp;
- if (apr_strtoff(&size, cl, &errp, 10) || *errp || size < 0) {
- cl = NULL; /* parse error, see next 'if' block */
- }
- }
-
if (!cl) {
/* if we don't get the content-length, see if we have all the
* buckets and use their length to calculate the size
Modified: httpd/httpd/branches/2.4.x/modules/cache/mod_cache_disk.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/cache/mod_cache_disk.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/cache/mod_cache_disk.c (original)
+++ httpd/httpd/branches/2.4.x/modules/cache/mod_cache_disk.c Wed Jul 8 11:09:13 2020
@@ -1276,9 +1276,9 @@ static apr_status_t store_body(cache_han
* sanity checks.
*/
if (seen_eos) {
- const char *cl_header = apr_table_get(r->headers_out, "Content-Length");
-
if (!dobj->disk_info.header_only) {
+ const char *cl_header;
+ apr_off_t cl;
if (dobj->data.tempfd) {
rv = apr_file_close(dobj->data.tempfd);
@@ -1297,6 +1297,7 @@ static apr_status_t store_body(cache_han
apr_pool_destroy(dobj->data.pool);
return APR_EGENERAL;
}
+
if (dobj->file_size < dconf->minfs) {
ap_log_rerror(
APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00734) "URL %s failed the size check "
@@ -1305,17 +1306,16 @@ static apr_status_t store_body(cache_han
apr_pool_destroy(dobj->data.pool);
return APR_EGENERAL;
}
- if (cl_header) {
- apr_int64_t cl = apr_atoi64(cl_header);
- if ((errno == 0) && (dobj->file_size != cl)) {
- ap_log_rerror(
- APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00735) "URL %s didn't receive complete response, not caching", h->cache_obj->key);
- /* Remove the intermediate cache file and return non-APR_SUCCESS */
- apr_pool_destroy(dobj->data.pool);
- return APR_EGENERAL;
- }
- }
+ cl_header = apr_table_get(r->headers_out, "Content-Length");
+ if (cl_header && (!ap_parse_strict_length(&cl, cl_header)
+ || cl != dobj->file_size)) {
+ ap_log_rerror(
+ APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(00735) "URL %s didn't receive complete response, not caching", h->cache_obj->key);
+ /* Remove the intermediate cache file and return non-APR_SUCCESS */
+ apr_pool_destroy(dobj->data.pool);
+ return APR_EGENERAL;
+ }
}
/* All checks were fine, we're good to go when the commit comes */
Modified: httpd/httpd/branches/2.4.x/modules/cache/mod_cache_socache.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/cache/mod_cache_socache.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/cache/mod_cache_socache.c (original)
+++ httpd/httpd/branches/2.4.x/modules/cache/mod_cache_socache.c Wed Jul 8 11:09:13 2020
@@ -1044,7 +1044,8 @@ static apr_status_t store_body(cache_han
/* Was this the final bucket? If yes, perform sanity checks.
*/
if (seen_eos) {
- const char *cl_header = apr_table_get(r->headers_out, "Content-Length");
+ const char *cl_header;
+ apr_off_t cl;
if (r->connection->aborted || r->no_cache) {
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(02380)
@@ -1055,18 +1056,16 @@ static apr_status_t store_body(cache_han
sobj->pool = NULL;
return APR_EGENERAL;
}
- if (cl_header) {
- apr_off_t cl;
- char *cl_endp;
- if (apr_strtoff(&cl, cl_header, &cl_endp, 10) != APR_SUCCESS
- || *cl_endp != '\0' || cl != sobj->body_length) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02381)
- "URL %s didn't receive complete response, not caching",
- h->cache_obj->key);
- apr_pool_destroy(sobj->pool);
- sobj->pool = NULL;
- return APR_EGENERAL;
- }
+
+ cl_header = apr_table_get(r->headers_out, "Content-Length");
+ if (cl_header && (!ap_parse_strict_length(&cl, cl_header)
+ || cl != sobj->body_length)) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02381)
+ "URL %s didn't receive complete response, not caching",
+ h->cache_obj->key);
+ apr_pool_destroy(sobj->pool);
+ sobj->pool = NULL;
+ return APR_EGENERAL;
}
/* All checks were fine, we're good to go when the commit comes */
Modified: httpd/httpd/branches/2.4.x/modules/dav/main/mod_dav.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/dav/main/mod_dav.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/dav/main/mod_dav.c (original)
+++ httpd/httpd/branches/2.4.x/modules/dav/main/mod_dav.c Wed Jul 8 11:09:13 2020
@@ -800,7 +800,6 @@ static int dav_parse_range(request_rec *
char *range;
char *dash;
char *slash;
- char *errp;
range_c = apr_table_get(r->headers_in, "content-range");
if (range_c == NULL)
@@ -817,20 +816,19 @@ static int dav_parse_range(request_rec *
*dash++ = *slash++ = '\0';
/* detect invalid ranges */
- if (apr_strtoff(range_start, range + 6, &errp, 10)
- || *errp || *range_start < 0) {
+ if (!ap_parse_strict_length(range_start, range + 6)) {
return -1;
}
- if (apr_strtoff(range_end, dash, &errp, 10)
- || *errp || *range_end < 0 || *range_end < *range_start) {
+ if (!ap_parse_strict_length(range_end, dash)
+ || *range_end < *range_start) {
return -1;
}
if (*slash != '*') {
apr_off_t dummy;
- if (apr_strtoff(&dummy, slash, &errp, 10)
- || *errp || dummy <= *range_end) {
+ if (!ap_parse_strict_length(&dummy, slash)
+ || dummy <= *range_end) {
return -1;
}
}
@@ -2485,20 +2483,13 @@ static int process_mkcol_body(request_re
r->read_chunked = 1;
}
else if (lenp) {
- const char *pos = lenp;
-
- while (apr_isdigit(*pos) || apr_isspace(*pos)) {
- ++pos;
- }
-
- if (*pos != '\0') {
+ if (!ap_parse_strict_length(&r->remaining, lenp)) {
+ r->remaining = 0;
/* This supplies additional information for the default message. */
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00590)
"Invalid Content-Length %s", lenp);
return HTTP_BAD_REQUEST;
}
-
- r->remaining = apr_atoi64(lenp);
}
if (r->read_chunked || r->remaining > 0) {
Modified: httpd/httpd/branches/2.4.x/modules/filters/mod_data.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/filters/mod_data.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/filters/mod_data.c (original)
+++ httpd/httpd/branches/2.4.x/modules/filters/mod_data.c Wed Jul 8 11:09:13 2020
@@ -107,8 +107,8 @@ static apr_status_t data_out_filter(ap_f
if (content_length) {
apr_off_t len, clen;
apr_brigade_length(ctx->bb, 1, &len);
- clen = apr_atoi64(content_length);
- if (clen >= 0 && clen < APR_INT32_MAX) {
+ if (ap_parse_strict_length(&clen, content_length)
+ && clen < APR_INT32_MAX) {
ap_set_content_length(r, len +
apr_base64_encode_len((int)clen) - 1);
}
Modified: httpd/httpd/branches/2.4.x/modules/filters/mod_reflector.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/filters/mod_reflector.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/filters/mod_reflector.c (original)
+++ httpd/httpd/branches/2.4.x/modules/filters/mod_reflector.c Wed Jul 8 11:09:13 2020
@@ -91,11 +91,16 @@ static int reflector_handler(request_rec
/* reflect the content length, if present */
if ((content_length = apr_table_get(r->headers_in, "Content-Length"))) {
- apr_off_t offset;
+ apr_off_t clen;
- apr_strtoff(&offset, content_length, NULL, 10);
- ap_set_content_length(r, offset);
+ if (!ap_parse_strict_length(&clen, content_length)) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(10243)
+ "reflector_handler: invalid content-length '%s'",
+ content_length);
+ return HTTP_BAD_REQUEST;
+ }
+ ap_set_content_length(r, clen);
}
/* reflect the content type, if present */
Modified: httpd/httpd/branches/2.4.x/modules/filters/mod_request.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/filters/mod_request.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/filters/mod_request.c (original)
+++ httpd/httpd/branches/2.4.x/modules/filters/mod_request.c Wed Jul 8 11:09:13 2020
@@ -76,7 +76,6 @@ static apr_status_t keep_body_filter(ap_
if (!ctx) {
const char *lenp;
- char *endstr = NULL;
request_dir_conf *dconf = ap_get_module_config(f->r->per_dir_config,
&request_module);
@@ -93,13 +92,12 @@ static apr_status_t keep_body_filter(ap_
if (lenp) {
/* Protects against over/underflow, non-digit chars in the
- * string (excluding leading space) (the endstr checks)
- * and a negative number. */
- if (apr_strtoff(&ctx->remaining, lenp, &endstr, 10)
- || endstr == lenp || *endstr || ctx->remaining < 0) {
-
+ * string, leading plus/minus signs, trailing characters and
+ * a negative number.
+ */
+ if (!ap_parse_strict_length(&ctx->remaining, lenp)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, APLOGNO(01411)
- "Invalid Content-Length");
+ "Invalid Content-Length '%s'", lenp);
ap_remove_input_filter(f);
return bail_out_on_error(b, f, HTTP_REQUEST_ENTITY_TOO_LARGE);
Modified: httpd/httpd/branches/2.4.x/modules/http/byterange_filter.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http/byterange_filter.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http/byterange_filter.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http/byterange_filter.c Wed Jul 8 11:09:13 2020
@@ -152,7 +152,6 @@ static int ap_set_byterange(request_rec
*indexes = apr_array_make(r->pool, ranges, sizeof(indexes_t));
while ((cur = ap_getword(r->pool, &range, ','))) {
char *dash;
- char *errp;
apr_off_t number, start, end;
if (!*cur)
@@ -169,7 +168,7 @@ static int ap_set_byterange(request_rec
if (dash == cur) {
/* In the form "-5" */
- if (apr_strtoff(&number, dash+1, &errp, 10) || *errp) {
+ if (!ap_parse_strict_length(&number, dash+1)) {
return 0;
}
if (number < 1) {
@@ -180,12 +179,12 @@ static int ap_set_byterange(request_rec
}
else {
*dash++ = '\0';
- if (apr_strtoff(&number, cur, &errp, 10) || *errp) {
+ if (!ap_parse_strict_length(&number, cur)) {
return 0;
}
start = number;
if (*dash) {
- if (apr_strtoff(&number, dash, &errp, 10) || *errp) {
+ if (!ap_parse_strict_length(&number, dash)) {
return 0;
}
end = number;
Modified: httpd/httpd/branches/2.4.x/modules/http/http_filters.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/http/http_filters.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/http/http_filters.c (original)
+++ httpd/httpd/branches/2.4.x/modules/http/http_filters.c Wed Jul 8 11:09:13 2020
@@ -405,16 +405,13 @@ apr_status_t ap_http_filter(ap_filter_t
lenp = NULL;
}
if (lenp) {
- char *endstr;
-
ctx->state = BODY_LENGTH;
/* Protects against over/underflow, non-digit chars in the
- * string (excluding leading space) (the endstr checks)
- * and a negative number. */
- if (apr_strtoff(&ctx->remaining, lenp, &endstr, 10)
- || endstr == lenp || *endstr || ctx->remaining < 0) {
-
+ * string, leading plus/minus signs, trailing characters and
+ * a negative number.
+ */
+ if (!ap_parse_strict_length(&ctx->remaining, lenp)) {
ctx->remaining = 0;
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, f->r, APLOGNO(01587)
"Invalid Content-Length");
@@ -1734,13 +1731,10 @@ AP_DECLARE(int) ap_setup_client_block(re
r->read_chunked = 1;
}
else if (lenp) {
- char *endstr;
-
- if (apr_strtoff(&r->remaining, lenp, &endstr, 10)
- || *endstr || r->remaining < 0) {
+ if (!ap_parse_strict_length(&r->remaining, lenp)) {
r->remaining = 0;
ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, APLOGNO(01594)
- "Invalid Content-Length");
+ "Invalid Content-Length '%s'", lenp);
return HTTP_BAD_REQUEST;
}
}
Modified: httpd/httpd/branches/2.4.x/modules/mappers/mod_negotiation.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/mappers/mod_negotiation.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/mappers/mod_negotiation.c (original)
+++ httpd/httpd/branches/2.4.x/modules/mappers/mod_negotiation.c Wed Jul 8 11:09:13 2020
@@ -988,19 +988,17 @@ static int read_type_map(apr_file_t **ma
has_content = 1;
}
else if (!strncmp(buffer, "content-length:", 15)) {
- char *errp;
- apr_off_t number;
+ apr_off_t clen;
body1 = ap_get_token(neg->pool, &body, 0);
- if (apr_strtoff(&number, body1, &errp, 10) != APR_SUCCESS
- || *errp || number < 0) {
+ if (!ap_parse_strict_length(&clen, body1)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00684)
"Parse error in type map, Content-Length: "
"'%s' in %s is invalid.",
body1, r->filename);
break;
}
- mime_info.bytes = number;
+ mime_info.bytes = clen;
has_content = 1;
}
else if (!strncmp(buffer, "content-language:", 17)) {
Modified: httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.c (original)
+++ httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy.c Wed Jul 8 11:09:13 2020
@@ -1208,7 +1208,6 @@ static int proxy_handler(request_rec *r)
/* Did the scheme handler process the request? */
if (access_status != DECLINED) {
const char *cl_a;
- char *end;
apr_off_t cl;
/*
@@ -1218,18 +1217,17 @@ static int proxy_handler(request_rec *r)
if (access_status != HTTP_BAD_GATEWAY) {
goto cleanup;
}
+
cl_a = apr_table_get(r->headers_in, "Content-Length");
- if (cl_a) {
- apr_strtoff(&cl, cl_a, &end, 10);
+ if (cl_a && (!ap_parse_strict_length(&cl, cl_a)
+ || cl > 0)) {
/*
* The request body is of length > 0. We cannot
* retry with a direct connection since we already
* sent (parts of) the request body to the proxy
* and do not have any longer.
*/
- if (cl > 0) {
- goto cleanup;
- }
+ goto cleanup;
}
/*
* Transfer-Encoding was set as input header, so we had
Modified: httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ajp.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ajp.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ajp.c (original)
+++ httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_ajp.c Wed Jul 8 11:09:13 2020
@@ -126,11 +126,8 @@ static apr_off_t get_content_length(requ
if (r->main == NULL) {
const char *clp = apr_table_get(r->headers_in, "Content-Length");
- if (clp) {
- char *errp;
- if (apr_strtoff(&len, clp, &errp, 10) || *errp || len < 0) {
- len = 0; /* parse error */
- }
+ if (clp && !ap_parse_strict_length(&len, clp)) {
+ len = -1; /* parse error */
}
}
@@ -255,10 +252,14 @@ static int ap_proxy_ajp_request(apr_pool
} else {
/* Get client provided Content-Length header */
content_length = get_content_length(r);
- status = ap_get_brigade(r->input_filters, input_brigade,
- AP_MODE_READBYTES, APR_BLOCK_READ,
- maxsize - AJP_HEADER_SZ);
-
+ if (content_length < 0) {
+ status = APR_EINVAL;
+ }
+ else {
+ status = ap_get_brigade(r->input_filters, input_brigade,
+ AP_MODE_READBYTES, APR_BLOCK_READ,
+ maxsize - AJP_HEADER_SZ);
+ }
if (status != APR_SUCCESS) {
/* We had a failure: Close connection to backend */
conn->close = 1;
Modified: httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_http.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_http.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_http.c (original)
+++ httpd/httpd/branches/2.4.x/modules/proxy/mod_proxy_http.c Wed Jul 8 11:09:13 2020
@@ -769,9 +769,7 @@ static int ap_proxy_http_prefetch(proxy_
}
else if (req->old_cl_val) {
if (r->input_filters == r->proto_input_filters) {
- char *endstr;
- status = apr_strtoff(&req->cl_val, req->old_cl_val, &endstr, 10);
- if (status != APR_SUCCESS || *endstr || req->cl_val < 0) {
+ if (!ap_parse_strict_length(&req->cl_val, req->old_cl_val)) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, APLOGNO(01085)
"could not parse request Content-Length (%s)",
req->old_cl_val);
Modified: httpd/httpd/branches/2.4.x/server/protocol.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/server/protocol.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/server/protocol.c (original)
+++ httpd/httpd/branches/2.4.x/server/protocol.c Wed Jul 8 11:09:13 2020
@@ -1367,7 +1367,7 @@ request_rec *ap_read_request(conn_rec *c
}
if (!r->assbackwards) {
- const char *tenc;
+ const char *tenc, *clen;
ap_get_mime_headers_core(r, tmp_bb);
if (r->status != HTTP_OK) {
@@ -1380,9 +1380,27 @@ request_rec *ap_read_request(conn_rec *c
goto traceout;
}
+ clen = apr_table_get(r->headers_in, "Content-Length");
+ if (clen) {
+ apr_off_t cl;
+
+ if (!ap_parse_strict_length(&cl, clen)) {
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(10242)
+ "client sent invalid Content-Length "
+ "(%s): %s", clen, r->uri);
+ r->status = HTTP_BAD_REQUEST;
+ conn->keepalive = AP_CONN_CLOSE;
+ ap_send_error_response(r, 0);
+ ap_update_child_status(conn->sbh, SERVER_BUSY_LOG, r);
+ ap_run_log_transaction(r);
+ apr_brigade_destroy(tmp_bb);
+ goto traceout;
+ }
+ }
+
tenc = apr_table_get(r->headers_in, "Transfer-Encoding");
if (tenc) {
- /* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23
+ /* https://tools.ietf.org/html/rfc7230
* Section 3.3.3.3: "If a Transfer-Encoding header field is
* present in a request and the chunked transfer coding is not
* the final encoding ...; the server MUST respond with the 400
@@ -1401,13 +1419,20 @@ request_rec *ap_read_request(conn_rec *c
goto traceout;
}
- /* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-23
+ /* https://tools.ietf.org/html/rfc7230
* Section 3.3.3.3: "If a message is received with both a
* Transfer-Encoding and a Content-Length header field, the
* Transfer-Encoding overrides the Content-Length. ... A sender
* MUST remove the received Content-Length field".
*/
- apr_table_unset(r->headers_in, "Content-Length");
+ if (clen) {
+ apr_table_unset(r->headers_in, "Content-Length");
+
+ /* Don't reuse this connection anyway to avoid confusion with
+ * intermediaries and request/reponse spltting.
+ */
+ conn->keepalive = AP_CONN_CLOSE;
+ }
}
}
Modified: httpd/httpd/branches/2.4.x/server/util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/branches/2.4.x/server/util.c?rev=1879639&r1=1879638&r2=1879639&view=diff
==============================================================================
--- httpd/httpd/branches/2.4.x/server/util.c (original)
+++ httpd/httpd/branches/2.4.x/server/util.c Wed Jul 8 11:09:13 2020
@@ -2589,6 +2589,15 @@ AP_DECLARE(apr_status_t) ap_timeout_para
return APR_SUCCESS;
}
+AP_DECLARE(int) ap_parse_strict_length(apr_off_t *len, const char *str)
+{
+ char *end;
+
+ return (apr_isdigit(*str)
+ && apr_strtoff(len, str, &end, 10) == APR_SUCCESS
+ && *end == '\0');
+}
+
/**
* Determine if a request has a request body or not.
*
@@ -2598,20 +2607,13 @@ AP_DECLARE(apr_status_t) ap_timeout_para
AP_DECLARE(int) ap_request_has_body(request_rec *r)
{
apr_off_t cl;
- char *estr;
const char *cls;
- int has_body;
- has_body = (!r->header_only
- && (r->kept_body
- || apr_table_get(r->headers_in, "Transfer-Encoding")
- || ( (cls = apr_table_get(r->headers_in, "Content-Length"))
- && (apr_strtoff(&cl, cls, &estr, 10) == APR_SUCCESS)
- && (!*estr)
- && (cl > 0) )
- )
- );
- return has_body;
+ return (!r->header_only
+ && (r->kept_body
+ || apr_table_get(r->headers_in, "Transfer-Encoding")
+ || ((cls = apr_table_get(r->headers_in, "Content-Length"))
+ && ap_parse_strict_length(&cl, cls) && cl > 0)));
}
AP_DECLARE_NONSTD(apr_status_t) ap_pool_cleanup_set_null(void *data_)