From 0bca294f9decf2fc27a43d7b6ce76f2d9d43be9b Mon Sep 17 00:00:00 2001 From: Jim Jagielski Date: Tue, 11 Feb 2020 13:19:05 +0000 Subject: [PATCH] Merge r1873748 from trunk: factor out TE=chunked checking Submitted by: covener Reviewed by: covener, minfrin, jorton git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1873906 13f79535-47bb-0310-9956-ffa450edef68 --- STATUS | 6 ----- include/ap_mmn.h | 3 ++- include/httpd.h | 9 ++++++++ modules/http/http_filters.c | 3 +-- modules/http/http_protocol.c | 5 ++-- server/protocol.c | 3 +-- server/util.c | 44 ++++++++++++++++++++++++++++++++---- 7 files changed, 54 insertions(+), 19 deletions(-) diff --git a/STATUS b/STATUS index 4afd862b385..244b8fc2dec 100644 --- a/STATUS +++ b/STATUS @@ -133,12 +133,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - *) factor out chunked TE checks - trunk patch: http://svn.apache.org/r1873748 - 2.4.x patch: http://people.apache.org/~covener/patches/httpd-2.4.x-chunk.diff - (MMN conflicts) - +1: covener, minfrin, jorton - *) mod_ssl: negotiate the TLS protocol version per name based vhost... trunk patch: http://svn.apache.org/r1868645 http://svn.apache.org/r1868743 diff --git a/include/ap_mmn.h b/include/ap_mmn.h index acdf7f1b1ad..70300f43308 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -532,6 +532,7 @@ * 20120211.89 (2.4.42-dev) Add add dns_pool to proxy_conn_pool and define * AP_VOLATILIZE_T. * 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 */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */ @@ -539,7 +540,7 @@ #ifndef MODULE_MAGIC_NUMBER_MAJOR #define MODULE_MAGIC_NUMBER_MAJOR 20120211 #endif -#define MODULE_MAGIC_NUMBER_MINOR 90 /* 0...n */ +#define MODULE_MAGIC_NUMBER_MINOR 91 /* 0...n */ /** * Determine if the server's current MODULE_MAGIC_NUMBER is at least a diff --git a/include/httpd.h b/include/httpd.h index 77d42c62a7c..4a7b2f40a15 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -2495,6 +2495,15 @@ AP_DECLARE(const char *)ap_dir_nofnmatch(ap_dir_match_t *w, const char *fname) AP_DECLARE(const char *)ap_dir_fnmatch(ap_dir_match_t *w, const char *path, const char *fname) __attribute__((nonnull(1,3))); +/** + * Determine if the final Transfer-Encoding is "chunked". + * + * @param p The pool to allocate from + * @param line the header field-value to scan + * @return 1 if the last Transfer-Encoding is "chunked", else 0 + */ +AP_DECLARE(int) ap_is_chunked(apr_pool_t *p, const char *line); + #ifdef __cplusplus } #endif diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c index 5fc44e542f2..d507d1695ed 100644 --- a/modules/http/http_filters.c +++ b/modules/http/http_filters.c @@ -379,8 +379,7 @@ apr_status_t ap_http_filter(ap_filter_t *f, apr_bucket_brigade *b, lenp = apr_table_get(f->r->headers_in, "Content-Length"); if (tenc) { - if (strcasecmp(tenc, "chunked") == 0 /* fast path */ - || ap_find_last_token(f->r->pool, tenc, "chunked")) { + if (ap_is_chunked(f->r->pool, tenc)) { ctx->state = BODY_CHUNK; } else if (f->r->proxyreq == PROXYREQ_RESPONSE) { diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index dcafa9c68af..e0ed8d50d52 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -257,10 +257,9 @@ AP_DECLARE(int) ap_set_keepalive(request_rec *r) && (r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status) || apr_table_get(r->headers_out, "Content-Length") - || ap_find_last_token(r->pool, + || ap_is_chunked(r->pool, apr_table_get(r->headers_out, - "Transfer-Encoding"), - "chunked") + "Transfer-Encoding")) || ((r->proto_num >= HTTP_VERSION(1,1)) && (r->chunked = 1))) /* THIS CODE IS CORRECT, see above. */ && r->server->keep_alive diff --git a/server/protocol.c b/server/protocol.c index 6864ed0d0a7..8e717fb0bd3 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -1388,8 +1388,7 @@ request_rec *ap_read_request(conn_rec *conn) * the final encoding ...; the server MUST respond with the 400 * (Bad Request) status code and then close the connection". */ - if (!(strcasecmp(tenc, "chunked") == 0 /* fast path */ - || ap_find_last_token(r->pool, tenc, "chunked"))) { + if (!ap_is_chunked(r->pool, tenc)) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(02539) "client sent unknown Transfer-Encoding " "(%s): %s", tenc, r->uri); diff --git a/server/util.c b/server/util.c index d1f3c626514..bfc9cf996d7 100644 --- a/server/util.c +++ b/server/util.c @@ -1708,14 +1708,13 @@ AP_DECLARE(int) ap_find_token(apr_pool_t *p, const char *line, const char *tok) } } - -AP_DECLARE(int) ap_find_last_token(apr_pool_t *p, const char *line, - const char *tok) +static const char *find_last_token(apr_pool_t *p, const char *line, + const char *tok) { int llen, tlen, lidx; if (!line) - return 0; + return NULL; llen = strlen(line); tlen = strlen(tok); @@ -1723,9 +1722,44 @@ AP_DECLARE(int) ap_find_last_token(apr_pool_t *p, const char *line, if (lidx < 0 || (lidx > 0 && !(apr_isspace(line[lidx - 1]) || line[lidx - 1] == ','))) + return NULL; + + if (ap_cstr_casecmpn(&line[lidx], tok, tlen) == 0) { + return &line[lidx]; + } + return NULL; +} + +AP_DECLARE(int) ap_find_last_token(apr_pool_t *p, const char *line, + const char *tok) +{ + return find_last_token(p, line, tok) != NULL; +} + +AP_DECLARE(int) ap_is_chunked(apr_pool_t *p, const char *line) +{ + const char *s; + + if (!line) return 0; + if (!ap_cstr_casecmp(line, "chunked")) { + return 1; + } - return (strncasecmp(&line[lidx], tok, tlen) == 0); + s = find_last_token(p, line, "chunked"); + + if (!s) return 0; + + /* eat spaces right-to-left to see what precedes "chunked" */ + while (--s > line) { + if (*s != ' ') break; + } + + /* found delim, or leading ws (input wasn't parsed by httpd as a header) */ + if (*s == ',' || *s == ' ') { + return 1; + } + return 0; } AP_DECLARE(char *) ap_escape_shell_cmd(apr_pool_t *p, const char *str) -- 2.47.3