Do we want this for the 2.2 release? On Thu, Jan 5, 2017 at 7:31 AM, <yla...@apache.org> wrote: > Author: ylavic > Date: Thu Jan 5 12:31:48 2017 > New Revision: 1777460 > > URL: http://svn.apache.org/viewvc?rev=1777460&view=rev > Log: > http: allow folding in check_headers(), still compliant with RFC 7230 (3.2.4). > > Modified: > httpd/httpd/trunk/modules/http/http_filters.c > > Modified: httpd/httpd/trunk/modules/http/http_filters.c > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http/http_filters.c?rev=1777460&r1=1777459&r2=1777460&view=diff > ============================================================================== > --- httpd/httpd/trunk/modules/http/http_filters.c (original) > +++ httpd/httpd/trunk/modules/http/http_filters.c Thu Jan 5 12:31:48 2017 > @@ -631,14 +631,16 @@ apr_status_t ap_http_filter(ap_filter_t > > struct check_header_ctx { > request_rec *r; > - int strict; > + unsigned int strict:1, > + unfold:1; > }; > > /* check a single header, to be used with apr_table_do() */ > -static int check_header(void *arg, const char *name, const char *val) > +static int check_header(struct check_header_ctx *ctx, > + const char *name, const char **val) > { > - struct check_header_ctx *ctx = arg; > - const char *test; > + const char *pos, *end; > + char *dst = NULL; > > if (name[0] == '\0') { > ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, APLOGNO(02428) > @@ -647,12 +649,12 @@ static int check_header(void *arg, const > } > > if (ctx->strict) { > - test = ap_scan_http_token(name); > + end = ap_scan_http_token(name); > } > else { > - test = ap_scan_vchar_obstext(name); > + end = ap_scan_vchar_obstext(name); > } > - if (*test) { > + if (*end) { > ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, APLOGNO(02429) > "Response header name '%s' contains invalid " > "characters, aborting request", > @@ -660,13 +662,54 @@ static int check_header(void *arg, const > return 0; > } > > - test = ap_scan_http_field_content(val); > - if (*test) { > - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, APLOGNO(02430) > - "Response header '%s' value of '%s' contains invalid " > - "characters, aborting request", > - name, val); > - return 0; > + for (pos = *val; *pos; pos = end) { > + end = ap_scan_http_field_content(pos); > + if (*end) { > + if (end[0] != CR || end[1] != LF || (end[2] != ' ' && > + end[2] != '\t')) { > + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, ctx->r, > APLOGNO(02430) > + "Response header '%s' value of '%s' contains " > + "invalid characters, aborting request", > + name, pos); > + return 0; > + } > + if (!ctx->unfold) { > + end += 3; > + } > + else if (!dst) { > + *val = dst = apr_palloc(ctx->r->pool, strlen(*val) + 1); > + } > + } > + if (dst) { > + memcpy(dst, pos, end - pos); > + dst += end - pos; > + if (*end) { > + /* skip folding and replace with a single space */ > + end += 3 + strspn(end + 3, "\t "); > + *dst++ = ' '; > + } > + } > + } > + if (dst) { > + *dst = '\0'; > + } > + return 1; > +} > + > +static int check_headers_table(apr_table_t *t, struct check_header_ctx *ctx) > +{ > + const apr_array_header_t *headers = apr_table_elts(t); > + apr_table_entry_t *header; > + int i; > + > + for (i = 0; i < headers->nelts; ++i) { > + header = &APR_ARRAY_IDX(headers, i, apr_table_entry_t); > + if (!header->key) { > + continue; > + } > + if (!check_header(ctx, header->key, (const char **)&header->val)) { > + return 0; > + } > } > return 1; > } > @@ -683,8 +726,10 @@ static APR_INLINE int check_headers(requ > > ctx.r = r; > ctx.strict = (conf->http_conformance != AP_HTTP_CONFORMANCE_UNSAFE); > - return apr_table_do(check_header, &ctx, r->headers_out, NULL) && > - apr_table_do(check_header, &ctx, r->err_headers_out, NULL); > + ctx.unfold = (!r->content_type || strncmp(r->content_type, > + "message/http", 12)); > + return check_headers_table(r->headers_out, &ctx) && > + check_headers_table(r->err_headers_out, &ctx); > } > > static int check_headers_recursion(request_rec *r) > >
-- Eric Covener cove...@gmail.com