Mailing List Archive

svn commit: r1863276 - in /httpd/httpd/trunk: CHANGES modules/http2/h2_stream.c
Author: icing
Date: Thu Jul 18 12:31:01 2019
New Revision: 1863276

URL: http://svn.apache.org/viewvc?rev=1863276&view=rev
Log:
*) mod_http2: core setting "LimitRequestFieldSize" is not additionally checked on
merged header fields, just as HTTP/1.1 does. [Stefan Eissing, Michael Kaufmann]


Modified:
httpd/httpd/trunk/CHANGES
httpd/httpd/trunk/modules/http2/h2_stream.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1863276&r1=1863275&r2=1863276&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Thu Jul 18 12:31:01 2019
@@ -1,6 +1,9 @@
-*- coding: utf-8 -*-
Changes with Apache 2.5.1

+ *) mod_http2: core setting "LimitRequestFieldSize" is not additionally checked on
+ merged header fields, just as HTTP/1.1 does. [Stefan Eissing, Michael Kaufmann]
+
*) mod_http2: fixed a bug that prevented proper stream cleanup when connection
throttling was in place. Stream resets by clients on streams initiated by them
are counted as possible trigger for throttling. [Stefan Eissing]

Modified: httpd/httpd/trunk/modules/http2/h2_stream.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/http2/h2_stream.c?rev=1863276&r1=1863275&r2=1863276&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/http2/h2_stream.c (original)
+++ httpd/httpd/trunk/modules/http2/h2_stream.c Thu Jul 18 12:31:01 2019
@@ -398,12 +398,7 @@ apr_status_t h2_stream_send_frame(h2_str
ap_assert(stream->request == NULL);
ap_assert(stream->rtmp != NULL);
status = h2_stream_end_headers(stream, 1, 0);
- if (status != APR_SUCCESS) {
- return status;
- }
- set_policy_for(stream, stream->rtmp);
- stream->request = stream->rtmp;
- stream->rtmp = NULL;
+ if (status != APR_SUCCESS) goto leave;
break;

default:
@@ -415,6 +410,7 @@ apr_status_t h2_stream_send_frame(h2_str
if (status == APR_SUCCESS && eos) {
status = transit(stream, on_event(stream, H2_SEV_CLOSED_L));
}
+leave:
return status;
}

@@ -456,12 +452,7 @@ apr_status_t h2_stream_recv_frame(h2_str
return APR_EINVAL;
}
status = h2_stream_end_headers(stream, eos, frame_len);
- if (status != APR_SUCCESS) {
- return status;
- }
- set_policy_for(stream, stream->rtmp);
- stream->request = stream->rtmp;
- stream->rtmp = NULL;
+ if (status != APR_SUCCESS) goto leave;
}
break;

@@ -472,6 +463,7 @@ apr_status_t h2_stream_recv_frame(h2_str
if (status == APR_SUCCESS && eos) {
status = transit(stream, on_event(stream, H2_SEV_CLOSED_R));
}
+leave:
return status;
}

@@ -761,9 +753,45 @@ apr_status_t h2_stream_add_header(h2_str
return status;
}

+typedef struct {
+ apr_size_t maxlen;
+ const char *failed_key;
+} val_len_check_ctx;
+
+static int table_check_val_len(void *baton, const char *key, const char *value)
+{
+ val_len_check_ctx *ctx = baton;
+
+ if (strlen(value) <= ctx->maxlen) return 1;
+ ctx->failed_key = key;
+ return 0;
+}
+
apr_status_t h2_stream_end_headers(h2_stream *stream, int eos, size_t raw_bytes)
{
- return h2_request_end_headers(stream->rtmp, stream->pool, eos, raw_bytes);
+ apr_status_t status;
+ val_len_check_ctx ctx;
+
+ status = h2_request_end_headers(stream->rtmp, stream->pool, eos, raw_bytes);
+ if (APR_SUCCESS == status) {
+ set_policy_for(stream, stream->rtmp);
+ stream->request = stream->rtmp;
+ stream->rtmp = NULL;
+
+ ctx.maxlen = stream->session->s->limit_req_fieldsize;
+ ctx.failed_key = NULL;
+ apr_table_do(table_check_val_len, &ctx, stream->request->headers, NULL);
+ if (ctx.failed_key) {
+ ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, stream->session->c,
+ H2_STRM_LOG(APLOGNO(), stream,"Request header exceeds "
+ "LimitRequestFieldSize: %.*s"),
+ (int)H2MIN(strlen(ctx.failed_key), 80), ctx.failed_key);
+ set_error_response(stream, HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE);
+ /* keep on returning APR_SUCCESS, so that we send a HTTP response and
+ * do not RST the stream. */
+ }
+ }
+ return status;
}

static apr_bucket *get_first_headers_bucket(apr_bucket_brigade *bb)