This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 8514e279d3226efed55bcf7690f948bc331c1c27 Author: opencode <[email protected]> AuthorDate: Tue Oct 13 14:40:53 2026 +0200 Validate the initial flow control window size provided by the administrator validateInitialWindowSize() only rejected values above the specification maximum (2^31-1). Negative values, which can only come from the (trusted) initialWindowSize connector attribute, passed validation and were silently truncated to 32 bits when serialized in the SETTINGS frame (e.g. -1 was advertised as 4294967295, which a conformant client must treat as a connection error of type FLOW_CONTROL_ERROR). They also caused an IllegalArgumentException from ByteBuffer.allocate()/new byte[] when the stream input buffers were first created. Reject negative values in validateInitialWindowSize() so the invalid configuration is reported when the HTTP/2 connection is opened, document the permitted range (0 to 2^31-1) on the Http2Protocol setter and in the HTTP/2 connector documentation, and add unit tests for the local settings validation paths. The remote path is unaffected: settings values read from the wire via ByteUtil.getFourBytes() are always in the unsigned 32-bit range 0 to 2^32-1. --- .../coyote/http2/ConnectionSettingsBase.java | 5 +++ java/org/apache/coyote/http2/Http2Protocol.java | 4 +- .../apache/coyote/http2/LocalStrings.properties | 1 + .../coyote/http2/TestConnectionSettingsLocal.java | 45 ++++++++++++++++++++++ webapps/docs/config/http2.xml | 5 ++- 5 files changed, 58 insertions(+), 2 deletions(-) diff --git a/java/org/apache/coyote/http2/ConnectionSettingsBase.java b/java/org/apache/coyote/http2/ConnectionSettingsBase.java index b9911d98b1..a6439202f1 100644 --- a/java/org/apache/coyote/http2/ConnectionSettingsBase.java +++ b/java/org/apache/coyote/http2/ConnectionSettingsBase.java @@ -222,6 +222,11 @@ abstract class ConnectionSettingsBase<T extends Throwable> { private void validateInitialWindowSize(long initialWindowSize) throws T { + if (initialWindowSize < 0) { + String msg = sm.getString("connectionSettings.windowSizeTooSmall", connectionId, + Long.toString(initialWindowSize)); + throwException(msg, Http2Error.FLOW_CONTROL_ERROR); + } if (initialWindowSize > MAX_WINDOW_SIZE) { String msg = sm.getString("connectionSettings.windowSizeTooBig", connectionId, Long.toString(initialWindowSize), Long.toString(MAX_WINDOW_SIZE)); diff --git a/java/org/apache/coyote/http2/Http2Protocol.java b/java/org/apache/coyote/http2/Http2Protocol.java index 6f1ee42ca5..a301cc692a 100644 --- a/java/org/apache/coyote/http2/Http2Protocol.java +++ b/java/org/apache/coyote/http2/Http2Protocol.java @@ -382,7 +382,9 @@ public class Http2Protocol implements UpgradeProtocol { /** - * Sets the initial window size advertised to the client. + * Sets the initial window size advertised to the client. The value must be in the range {@code 0} to + * {@code 2^31-1} (both inclusive) as defined by the HTTP/2 specification. Values outside of this range will cause + * HTTP/2 connections to be rejected. * * @param initialWindowSize the initial window size */ diff --git a/java/org/apache/coyote/http2/LocalStrings.properties b/java/org/apache/coyote/http2/LocalStrings.properties index e60f7ca7c7..f469dc7151 100644 --- a/java/org/apache/coyote/http2/LocalStrings.properties +++ b/java/org/apache/coyote/http2/LocalStrings.properties @@ -32,6 +32,7 @@ connectionSettings.maxFrameSizeInvalid=Connection [{0}], The requested maximum f connectionSettings.noRfc7540PrioritiesInvalid=Connection [{0}], The requested no RFC 7540 priorities setting [{1}] was not zero or one connectionSettings.unknown=Connection [{0}], An unknown setting with identifier [{1}] and value [{2}] was ignored connectionSettings.windowSizeTooBig=Connection [{0}], The requested window size of [{1}] is bigger than the maximum permitted value of [{2}] +connectionSettings.windowSizeTooSmall=Connection [{0}], The requested window size of [{1}] is smaller than the minimum permitted value of [0] frameType.checkPayloadSize=Payload size of [{0}] is not valid for frame type [{1}] frameType.checkStream=Invalid frame type [{0}] diff --git a/test/org/apache/coyote/http2/TestConnectionSettingsLocal.java b/test/org/apache/coyote/http2/TestConnectionSettingsLocal.java new file mode 100644 index 0000000000..dc48a5ee48 --- /dev/null +++ b/test/org/apache/coyote/http2/TestConnectionSettingsLocal.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.coyote.http2; + +import org.junit.Test; + +public class TestConnectionSettingsLocal { + + @Test(expected = IllegalArgumentException.class) + public void testInitialWindowSizeNegative() { + // Use of a negative value is not permitted by the specification and + // can not be represented in a SETTINGS frame + ConnectionSettingsLocal settings = new ConnectionSettingsLocal("0"); + settings.set(Setting.INITIAL_WINDOW_SIZE, -1); + } + + + @Test + public void testInitialWindowSizeZero() { + // A value of zero is permitted by the specification + ConnectionSettingsLocal settings = new ConnectionSettingsLocal("0"); + settings.set(Setting.INITIAL_WINDOW_SIZE, 0); + } + + + @Test(expected = IllegalArgumentException.class) + public void testInitialWindowSizeTooBig() { + ConnectionSettingsLocal settings = new ConnectionSettingsLocal("0"); + settings.set(Setting.INITIAL_WINDOW_SIZE, ConnectionSettingsBase.MAX_WINDOW_SIZE + 1L); + } +} diff --git a/webapps/docs/config/http2.xml b/webapps/docs/config/http2.xml index a87d1f7103..d65a2e812e 100644 --- a/webapps/docs/config/http2.xml +++ b/webapps/docs/config/http2.xml @@ -156,7 +156,10 @@ <attribute name="initialWindowSize" required="false"> <p>Controls the initial size of the flow control window for streams that - Tomcat advertises to clients. If not specified, the default value of + Tomcat advertises to clients. The value must be in the range <code>0</code> + to <code>2^31-1</code> (both inclusive) as defined by the HTTP/2 + specification. Values outside of this range will cause HTTP/2 connections + to be rejected. If not specified, the default value of <code>65535</code> is used.</p> </attribute> --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
