From b1197bfbc9a450235bd5b4ba489818e1f9959d11 Mon Sep 17 00:00:00 2001
From: small_leek
Date: Fri, 28 Feb 2020 20:54:21 -0500
Subject: [PATCH 1/2] package init
---
CVE-2018-11784.patch | 27 ++
CVE-2019-0199-1.patch | 75 ++++
CVE-2019-0199-10.patch | 13 +
CVE-2019-0199-11.patch | 21 ++
CVE-2019-0199-2.patch | 246 +++++++++++++
CVE-2019-0199-3.patch | 202 +++++++++++
CVE-2019-0199-4.patch | 38 ++
CVE-2019-0199-5.patch | 143 ++++++++
CVE-2019-0199-6.patch | 51 +++
CVE-2019-0199-7.patch | 32 ++
CVE-2019-0199-8.patch | 24 ++
CVE-2019-0199-9.patch | 24 ++
CVE-2019-0221.patch | 44 +++
CVE-2019-10072-1.patch | 129 +++++++
CVE-2019-10072-2.patch | 28 ++
apache-tomcat-9.0.10-src.tar.gz | Bin 0 -> 5147367 bytes
el-api-OSGi-MANIFEST.MF | 13 +
jasper-OSGi-MANIFEST.MF | 40 +++
jasper-el-OSGi-MANIFEST.MF | 13 +
jsp-api-OSGi-MANIFEST.MF | 13 +
servlet-api-OSGi-MANIFEST.MF | 17 +
tomcat-9.0-bootstrap-MANIFEST.MF.patch | 9 +
tomcat-9.0-digest.script | 45 +++
tomcat-9.0-jsvc.service | 22 ++
tomcat-9.0-tomcat-users-webapp.patch | 17 +
tomcat-9.0-tool-wrapper.script | 45 +++
tomcat-9.0.conf | 52 +++
tomcat-9.0.logrotate | 8 +
tomcat-9.0.service | 22 ++
tomcat-9.0.sysconfig | 11 +
tomcat-9.0.wrapper | 24 ++
tomcat-api-OSGi-MANIFEST.MF | 12 +
tomcat-build.patch | 12 +
tomcat-functions | 42 +++
tomcat-juli-OSGi-MANIFEST.MF | 13 +
tomcat-named.service | 26 ++
tomcat-preamble | 52 +++
tomcat-server | 25 ++
tomcat.spec | 463 +++++++++++++++++++++++++
39 files changed, 2093 insertions(+)
create mode 100644 CVE-2018-11784.patch
create mode 100644 CVE-2019-0199-1.patch
create mode 100644 CVE-2019-0199-10.patch
create mode 100644 CVE-2019-0199-11.patch
create mode 100644 CVE-2019-0199-2.patch
create mode 100644 CVE-2019-0199-3.patch
create mode 100644 CVE-2019-0199-4.patch
create mode 100644 CVE-2019-0199-5.patch
create mode 100644 CVE-2019-0199-6.patch
create mode 100644 CVE-2019-0199-7.patch
create mode 100644 CVE-2019-0199-8.patch
create mode 100644 CVE-2019-0199-9.patch
create mode 100644 CVE-2019-0221.patch
create mode 100644 CVE-2019-10072-1.patch
create mode 100644 CVE-2019-10072-2.patch
create mode 100644 apache-tomcat-9.0.10-src.tar.gz
create mode 100644 el-api-OSGi-MANIFEST.MF
create mode 100644 jasper-OSGi-MANIFEST.MF
create mode 100644 jasper-el-OSGi-MANIFEST.MF
create mode 100644 jsp-api-OSGi-MANIFEST.MF
create mode 100644 servlet-api-OSGi-MANIFEST.MF
create mode 100644 tomcat-9.0-bootstrap-MANIFEST.MF.patch
create mode 100644 tomcat-9.0-digest.script
create mode 100644 tomcat-9.0-jsvc.service
create mode 100644 tomcat-9.0-tomcat-users-webapp.patch
create mode 100644 tomcat-9.0-tool-wrapper.script
create mode 100644 tomcat-9.0.conf
create mode 100644 tomcat-9.0.logrotate
create mode 100644 tomcat-9.0.service
create mode 100644 tomcat-9.0.sysconfig
create mode 100644 tomcat-9.0.wrapper
create mode 100644 tomcat-api-OSGi-MANIFEST.MF
create mode 100644 tomcat-build.patch
create mode 100644 tomcat-functions
create mode 100644 tomcat-juli-OSGi-MANIFEST.MF
create mode 100644 tomcat-named.service
create mode 100644 tomcat-preamble
create mode 100644 tomcat-server
create mode 100644 tomcat.spec
diff --git a/CVE-2018-11784.patch b/CVE-2018-11784.patch
new file mode 100644
index 0000000..4bf1bb2
--- /dev/null
+++ b/CVE-2018-11784.patch
@@ -0,0 +1,27 @@
+--- a/webapps/docs/changelog.xml 2018-06-20 13:35:40.000000000 -0400
++++ b/webapps/docs/changelog_1.xml 2019-06-24 08:35:44.801000000 -0400
+@@ -164,6 +164,10 @@
+ the authenticated Subject to include at least one Principal of a type
+ specified by userClassNames. (markt)
+
++
++ When generating a redirect to a directory in the Default Servlet, avoid
++ generating a protocol relative redirect. (markt)
++
+
+
+
+--- a/java/org/apache/catalina/servlets/DefaultServlet.java 2018-06-20 13:35:34.000000000 -0400
++++ b/java/org/apache/catalina/servlets/DefaultServlet_1.java 2019-06-24 08:40:08.699000000 -0400
+@@ -1324,6 +1324,10 @@ public class DefaultServlet extends Http
+ location.append('?');
+ location.append(request.getQueryString());
+ }
++ // Avoid protocol relative redirects
++ while (location.length() > 1 && location.charAt(1) == '/') {
++ location.deleteCharAt(0);
++ }
+ response.sendRedirect(response.encodeRedirectURL(location.toString()));
+ }
+
+
diff --git a/CVE-2019-0199-1.patch b/CVE-2019-0199-1.patch
new file mode 100644
index 0000000..d05be52
--- /dev/null
+++ b/CVE-2019-0199-1.patch
@@ -0,0 +1,75 @@
+--- tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:17:08 1852697
++++ tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:01 1852698
+@@ -42,8 +42,10 @@
+ public class Http2Protocol implements UpgradeProtocol {
+
+ static final long DEFAULT_READ_TIMEOUT = 10000;
+- static final long DEFAULT_KEEP_ALIVE_TIMEOUT = -1;
+ static final long DEFAULT_WRITE_TIMEOUT = 10000;
++ static final long DEFAULT_KEEP_ALIVE_TIMEOUT = -1;
++ static final long DEFAULT_STREAM_READ_TIMEOUT = 20000;
++ static final long DEFAULT_STREAM_WRITE_TIMEOUT = 20000;
+ // The HTTP/2 specification recommends a minimum default of 100
+ static final long DEFAULT_MAX_CONCURRENT_STREAMS = 200;
+ // Maximum amount of streams which can be concurrently executed over
+@@ -57,9 +59,14 @@
+ private static final byte[] ALPN_IDENTIFIER = ALPN_NAME.getBytes(StandardCharsets.UTF_8);
+
+ // All timeouts in milliseconds
++ // These are the socket level timeouts
+ private long readTimeout = DEFAULT_READ_TIMEOUT;
+- private long keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT;
+ private long writeTimeout = DEFAULT_WRITE_TIMEOUT;
++ private long keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT;
++ // These are the stream level timeouts
++ private long streamReadTimeout = DEFAULT_STREAM_READ_TIMEOUT;
++ private long streamWriteTimeout = DEFAULT_STREAM_WRITE_TIMEOUT;
++
+ private long maxConcurrentStreams = DEFAULT_MAX_CONCURRENT_STREAMS;
+ private int maxConcurrentStreamExecution = DEFAULT_MAX_CONCURRENT_STREAM_EXECUTION;
+ // If a lower initial value is required, set it here but DO NOT change the
+@@ -145,6 +152,16 @@
+ }
+
+
++ public long getWriteTimeout() {
++ return writeTimeout;
++ }
++
++
++ public void setWriteTimeout(long writeTimeout) {
++ this.writeTimeout = writeTimeout;
++ }
++
++
+ public long getKeepAliveTimeout() {
+ return keepAliveTimeout;
+ }
+@@ -155,13 +172,23 @@
+ }
+
+
+- public long getWriteTimeout() {
+- return writeTimeout;
++ public long getStreamReadTimeout() {
++ return streamReadTimeout;
+ }
+
+
+- public void setWriteTimeout(long writeTimeout) {
+- this.writeTimeout = writeTimeout;
++ public void setStreamReadTimeout(long streamReadTimeout) {
++ this.streamReadTimeout = streamReadTimeout;
++ }
++
++
++ public long getStreamWriteTimeout() {
++ return streamWriteTimeout;
++ }
++
++
++ public void setStreamWriteTimeout(long streamWriteTimeout) {
++ this.streamWriteTimeout = streamWriteTimeout;
+ }
+
+
diff --git a/CVE-2019-0199-10.patch b/CVE-2019-0199-10.patch
new file mode 100644
index 0000000..fef53b2
--- /dev/null
+++ b/CVE-2019-0199-10.patch
@@ -0,0 +1,13 @@
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java 2019-06-09 21:03:54.790000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java 2019-06-09 21:05:12.133000000 -0400
+@@ -905,7 +905,7 @@ class Stream extends AbstractStream impl
+ throw new IOException(sm.getString("stream.inputBuffer.reset"));
+ }
+
+- if (inBuffer.position() == 0) {
++ if (inBuffer.position() == 0 && isActive() && !isInputFinished()) {
+ String msg = sm.getString("stream.inputBuffer.readTimeout");
+ StreamException se = new StreamException(
+ msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt());
+
diff --git a/CVE-2019-0199-11.patch b/CVE-2019-0199-11.patch
new file mode 100644
index 0000000..33e7526
--- /dev/null
+++ b/CVE-2019-0199-11.patch
@@ -0,0 +1,21 @@
+--- a/java/org/apache/coyote/http2/Stream.java 2019-06-11 21:24:19.998000000 -0400
++++ b/java/org/apache/coyote/http2/Stream_1.java 2019-06-11 21:26:18.329000000 -0400
+@@ -221,7 +221,7 @@ class Stream extends AbstractStream impl
+ if (windowSize == 0) {
+ String msg = sm.getString("stream.writeTimeout");
+ StreamException se = new StreamException(
+- msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt());
++ msg, Http2Error.ENHANCE_YOUR_CALM, getIdentifier().intValue());
+ // Prevent the application making further writes
+ streamOutputBuffer.closed = true;
+ // Prevent Tomcat's error handling trying to write
+@@ -908,7 +908,7 @@ class Stream extends AbstractStream impl
+ if (inBuffer.position() == 0 && isActive() && !isInputFinished()) {
+ String msg = sm.getString("stream.inputBuffer.readTimeout");
+ StreamException se = new StreamException(
+- msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt());
++ msg, Http2Error.ENHANCE_YOUR_CALM, getIdentifier().intValue());
+ // Trigger a reset once control returns to Tomcat
+ coyoteResponse.setError();
+ streamOutputBuffer.reset = se;
+
diff --git a/CVE-2019-0199-2.patch b/CVE-2019-0199-2.patch
new file mode 100644
index 0000000..c1c1fda
--- /dev/null
+++ b/CVE-2019-0199-2.patch
@@ -0,0 +1,246 @@
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/catalina/connector/OutputBuffer.java apache-tomcat-9.0.10-src-bak/java/org/apache/catalina/connector/OutputBuffer.java
+--- apache-tomcat-9.0.10-src/java/org/apache/catalina/connector/OutputBuffer.java 2018-06-20 13:35:33.000000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/catalina/connector/OutputBuffer.java 2019-06-09 20:28:02.836000000 -0400
+@@ -33,6 +33,7 @@ import javax.servlet.http.HttpServletRes
+
+ import org.apache.catalina.Globals;
+ import org.apache.coyote.ActionCode;
++import org.apache.coyote.CloseNowException;
+ import org.apache.coyote.Response;
+ import org.apache.tomcat.util.buf.C2BConverter;
+ import org.apache.tomcat.util.res.StringManager;
+@@ -326,6 +327,13 @@ public class OutputBuffer extends Writer
+ // real write to the adapter
+ try {
+ coyoteResponse.doWrite(buf);
++ } catch (CloseNowException e) {
++ // Catch this sub-class as it requires specific handling.
++ // Examples where this exception is thrown:
++ // - HTTP/2 stream timeout
++ // Prevent further output for this response
++ closed = true;
++ throw e;
+ } catch (IOException e) {
+ // An IOException on a write is almost always due to
+ // the remote client aborting the request. Wrap this
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/catalina/core/StandardWrapperValve.java apache-tomcat-9.0.10-src-bak/java/org/apache/catalina/core/StandardWrapperValve.java
+--- apache-tomcat-9.0.10-src/java/org/apache/catalina/core/StandardWrapperValve.java 2018-06-20 13:35:34.000000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/catalina/core/StandardWrapperValve.java 2019-06-09 20:33:27.596000000 -0400
+@@ -36,6 +36,7 @@ import org.apache.catalina.connector.Cli
+ import org.apache.catalina.connector.Request;
+ import org.apache.catalina.connector.Response;
+ import org.apache.catalina.valves.ValveBase;
++import org.apache.coyote.CloseNowException;
+ import org.apache.tomcat.util.ExceptionUtils;
+ import org.apache.tomcat.util.buf.MessageBytes;
+ import org.apache.tomcat.util.log.SystemLogHandler;
+@@ -201,7 +202,7 @@ final class StandardWrapperValve
+ }
+
+ }
+- } catch (ClientAbortException e) {
++ } catch (ClientAbortException | CloseNowException e) {
+ throwable = e;
+ exception(request, response, e);
+ } catch (IOException e) {
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/LocalStrings.properties apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/LocalStrings.properties
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/LocalStrings.properties 2018-06-20 13:35:35.000000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/LocalStrings.properties 2019-06-09 20:34:32.307000000 -0400
+@@ -93,6 +93,7 @@ stream.reset.fail=Connection [{0}], Stre
+ stream.reset.receive=Connection [{0}], Stream [{1}], Reset received due to [{2}]
+ stream.reset.send=Connection [{0}], Stream [{1}], Reset sent due to [{2}]
+ stream.trailerHeader.noEndOfStream=Connection [{0}], Stream [{1}], The trailer headers did not include the end of stream flag
++stream.writeTimeout=Timeout waiting for client to increase flow control window to permit stream data to be written
+
+ stream.inputBuffer.copy=Copying [{0}] bytes from inBuffer to outBuffer
+ stream.inputBuffer.dispatch=Data added to inBuffer when read interest is registered. Triggering a read dispatch
+@@ -149,4 +150,4 @@ upgradeHandler.writeHeaders=Connection [
+ upgradeHandler.writePushHeaders=Connection [{0}], Stream [{1}], Pushed stream [{2}], EndOfStream [{3}]
+
+ writeStateMachine.endWrite.ise=It is illegal to specify [{0}] for the new state once a write has completed
+-writeStateMachine.ise=It is illegal to call [{0}()] in state [{1}]
+\ No newline at end of file
++writeStateMachine.ise=It is illegal to call [{0}()] in state [{1}]
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java 2018-06-20 13:35:35.000000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java 2019-06-09 20:38:30.109000000 -0400
+@@ -211,7 +211,21 @@ class Stream extends AbstractStream impl
+ }
+ try {
+ if (block) {
+- wait();
++ wait(handler.getProtocol().getStreamWriteTimeout());
++ windowSize = getWindowSize();
++ if (windowSize == 0) {
++ String msg = sm.getString("stream.writeTimeout");
++ StreamException se = new StreamException(
++ msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt());
++ // Prevent the application making further writes
++ streamOutputBuffer.closed = true;
++ // Prevent Tomcat's error handling trying to write
++ coyoteResponse.setError();
++ coyoteResponse.setErrorReported();
++ // Trigger a reset once control returns to Tomcat
++ streamOutputBuffer.reset = se;
++ throw new CloseNowException(msg, se);
++ }
+ } else {
+ return 0;
+ }
+@@ -221,7 +235,6 @@ class Stream extends AbstractStream impl
+ // Stream.
+ throw new IOException(e);
+ }
+- windowSize = getWindowSize();
+ }
+ int allocation;
+ if (windowSize < reservation) {
+@@ -660,6 +673,9 @@ class Stream extends AbstractStream impl
+ return !streamOutputBuffer.endOfStreamSent;
+ }
+
++ StreamException getResetException() {
++ return streamOutputBuffer.reset;
++ }
+
+ private static void push(final Http2UpgradeHandler handler, final Request request,
+ final Stream stream) throws IOException {
+@@ -707,6 +723,7 @@ class Stream extends AbstractStream impl
+ private final ByteBuffer buffer = ByteBuffer.allocate(8 * 1024);
+ private volatile long written = 0;
+ private volatile boolean closed = false;
++ private volatile StreamException reset = null;
+ private volatile boolean endOfStreamSent = false;
+
+ /* The write methods are synchronized to ensure that only one thread at
+@@ -800,9 +817,14 @@ class Stream extends AbstractStream impl
+
+ @Override
+ public final void end() throws IOException {
+- closed = true;
+- flush(true);
+- writeTrailers();
++ if (reset != null) {
++ throw new CloseNowException(reset);
++ }
++ if (!closed) {
++ closed = true;
++ flush(true);
++ writeTrailers();
++ }
+ }
+
+ /**
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/StreamProcessor.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/StreamProcessor.java
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/StreamProcessor.java 2018-06-20 13:35:35.000000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/StreamProcessor.java 2019-06-09 20:40:08.789000000 -0400
+@@ -78,10 +78,13 @@ class StreamProcessor extends AbstractPr
+ stream.getIdentifier()), Http2Error.INTERNAL_ERROR);
+ stream.close(ce);
+ } else if (!getErrorState().isIoAllowed()) {
+- StreamException se = new StreamException(sm.getString(
+- "streamProcessor.error.stream", stream.getConnectionId(),
+- stream.getIdentifier()), Http2Error.INTERNAL_ERROR,
+- stream.getIdentifier().intValue());
++ StreamException se = stream.getResetException();
++ if (se == null) {
++ se = new StreamException(sm.getString(
++ "streamProcessor.error.stream", stream.getConnectionId(),
++ stream.getIdentifier()), Http2Error.INTERNAL_ERROR,
++ stream.getIdentifier().intValue());
++ }
+ stream.close(se);
+ }
+ }
+diff -Nurp apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/Http2TestBase.java apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/Http2TestBase.java
+--- apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/Http2TestBase.java 2018-06-20 13:35:38.000000000 -0400
++++ apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/Http2TestBase.java 2019-06-09 20:41:45.113000000 -0400
+@@ -486,8 +486,10 @@ public abstract class Http2TestBase exte
+ Http2Protocol http2Protocol = new Http2Protocol();
+ // Short timeouts for now. May need to increase these for CI systems.
+ http2Protocol.setReadTimeout(2000);
+- http2Protocol.setKeepAliveTimeout(5000);
+ http2Protocol.setWriteTimeout(2000);
++ http2Protocol.setKeepAliveTimeout(5000);
++ http2Protocol.setStreamReadTimeout(1000);
++ http2Protocol.setStreamWriteTimeout(1000);
+ http2Protocol.setMaxConcurrentStreams(maxConcurrentStreams);
+ connector.addUpgradeProtocol(http2Protocol);
+ }
+diff -Nurp apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/TestHttp2Timeouts.java apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/TestHttp2Timeouts.java
+--- apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/TestHttp2Timeouts.java 1969-12-31 19:00:00.000000000 -0500
++++ apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/TestHttp2Timeouts.java 2019-06-09 20:42:38.095000000 -0400
+@@ -0,0 +1,73 @@
++/*
++ * 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.Assert;
++import org.junit.Before;
++import org.junit.Test;
++
++public class TestHttp2Timeouts extends Http2TestBase {
++
++ @Override
++ @Before
++ public void http2Connect() throws Exception {
++ super.http2Connect();
++ sendSettings(0, false, new SettingValue(Setting.INITIAL_WINDOW_SIZE.getId(), 0));
++ }
++
++
++ /*
++ * Simple request won't fill buffer so timeout will occur in Tomcat internal
++ * code during response completion.
++ */
++ @Test
++ public void testClientWithEmptyWindow() throws Exception {
++ sendSimpleGetRequest(3);
++
++ // Settings
++ parser.readFrame(false);
++ // Headers
++ parser.readFrame(false);
++
++ output.clearTrace();
++
++ parser.readFrame(false);
++ Assert.assertEquals("3-RST-[11]\n", output.getTrace());
++ }
++
++
++ /*
++ * Large request will fill buffer so timeout will occur in application code
++ * during response write (when Tomcat commits the response and flushes the
++ * buffer as a result of the buffer filling).
++ */
++ @Test
++ public void testClientWithEmptyWindowLargeResponse() throws Exception {
++ sendLargeGetRequest(3);
++
++ // Settings
++ parser.readFrame(false);
++ // Headers
++ parser.readFrame(false);
++
++ output.clearTrace();
++
++ parser.readFrame(false);
++ Assert.assertEquals("3-RST-[11]\n", output.getTrace());
++ }
++
++}
diff --git a/CVE-2019-0199-3.patch b/CVE-2019-0199-3.patch
new file mode 100644
index 0000000..0494f3b
--- /dev/null
+++ b/CVE-2019-0199-3.patch
@@ -0,0 +1,202 @@
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/LocalStrings.properties apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/LocalStrings.properties
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/LocalStrings.properties 2019-06-09 20:45:15.320000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/LocalStrings.properties 2019-06-09 20:46:36.793000000 -0400
+@@ -98,6 +98,7 @@ stream.writeTimeout=Timeout waiting for
+ stream.inputBuffer.copy=Copying [{0}] bytes from inBuffer to outBuffer
+ stream.inputBuffer.dispatch=Data added to inBuffer when read interest is registered. Triggering a read dispatch
+ stream.inputBuffer.empty=The Stream input buffer is empty. Waiting for more data
++stream.inputBuffer.readTimeout=Timeout waiting to read data from client
+ stream.inputBuffer.reset=Stream reset
+ stream.inputBuffer.signal=Data added to inBuffer when read thread is waiting. Signalling that thread to continue
+
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java 2019-06-09 20:45:15.321000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java 2019-06-09 20:48:21.509000000 -0400
+@@ -888,10 +888,22 @@ class Stream extends AbstractStream impl
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("stream.inputBuffer.empty"));
+ }
+- inBuffer.wait();
++
++ inBuffer.wait(handler.getProtocol().getStreamReadTimeout());
++
+ if (reset) {
+ throw new IOException(sm.getString("stream.inputBuffer.reset"));
+ }
++
++ if (inBuffer.position() == 0) {
++ String msg = sm.getString("stream.inputBuffer.readTimeout");
++ StreamException se = new StreamException(
++ msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt());
++ // Trigger a reset once control returns to Tomcat
++ coyoteResponse.setError();
++ streamOutputBuffer.reset = se;
++ throw new CloseNowException(msg, se);
++ }
+ } catch (InterruptedException e) {
+ // Possible shutdown / rst or similar. Use an
+ // IOException to signal to the client that further I/O
+diff -Nurp apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/Http2TestBase.java apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/Http2TestBase.java
+--- apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/Http2TestBase.java 2019-06-09 20:45:15.323000000 -0400
++++ apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/Http2TestBase.java 2019-06-09 20:53:54.809000000 -0400
+@@ -28,6 +28,7 @@ import java.nio.charset.StandardCharsets
+ import java.util.ArrayList;
+ import java.util.List;
+ import java.util.Locale;
++import java.util.Map;
+ import java.util.Random;
+
+ import javax.net.SocketFactory;
+@@ -300,6 +301,22 @@ public abstract class Http2TestBase exte
+ }
+ }
+
++ protected void sendParameterPostRequest(int streamId, byte[] padding, String body,
++ long contentLength, boolean useExpectation) throws IOException {
++ byte[] headersFrameHeader = new byte[9];
++ ByteBuffer headersPayload = ByteBuffer.allocate(128);
++ byte[] dataFrameHeader = new byte[9];
++ ByteBuffer dataPayload = ByteBuffer.allocate(128);
++
++ buildPostRequest(headersFrameHeader, headersPayload, useExpectation,
++ "application/x-www-form-urlencoded", contentLength, "/parameter", dataFrameHeader,
++ dataPayload, padding, null, null, streamId);
++ writeFrame(headersFrameHeader, headersPayload);
++ if (body != null) {
++ dataPayload.put(body.getBytes(StandardCharsets.ISO_8859_1));
++ writeFrame(dataFrameHeader, dataPayload);
++ }
++ }
+
+ protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer headersPayload,
+ boolean useExpectation, byte[] dataFrameHeader, ByteBuffer dataPayload, byte[] padding,
+@@ -311,14 +328,29 @@ public abstract class Http2TestBase exte
+ protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer headersPayload,
+ boolean useExpectation, byte[] dataFrameHeader, ByteBuffer dataPayload, byte[] padding,
+ byte[] trailersFrameHeader, ByteBuffer trailersPayload, int streamId) {
++ buildPostRequest(headersFrameHeader, headersPayload, useExpectation, null, -1, "/simple",
++ dataFrameHeader, dataPayload, padding, trailersFrameHeader, trailersPayload, streamId);
++ }
++
++ protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer headersPayload,
++ boolean useExpectation, String contentType, long contentLength, String path,
++ byte[] dataFrameHeader, ByteBuffer dataPayload, byte[] padding,
++ byte[] trailersFrameHeader, ByteBuffer trailersPayload, int streamId) {
++
+ MimeHeaders headers = new MimeHeaders();
+ headers.addValue(":method").setString("POST");
+ headers.addValue(":scheme").setString("http");
+- headers.addValue(":path").setString("/simple");
++ headers.addValue(":path").setString(path);
+ headers.addValue(":authority").setString("localhost:" + getPort());
+ if (useExpectation) {
+ headers.addValue("expect").setString("100-continue");
+ }
++ if (contentType != null) {
++ headers.addValue("content-type").setString(contentType);
++ }
++ if (contentLength > -1) {
++ headers.addValue("content-length").setLong(contentLength);
++ }
+ hpackEncoder.encode(headers, headersPayload);
+
+ headersPayload.flip();
+@@ -507,6 +539,8 @@ public abstract class Http2TestBase exte
+ ctxt.addServletMappingDecoded("/large", "large");
+ Tomcat.addServlet(ctxt, "cookie", new CookieServlet());
+ ctxt.addServletMappingDecoded("/cookie", "cookie");
++ Tomcat.addServlet(ctxt, "parameter", new ParameterServlet());
++ ctxt.addServletMappingDecoded("/parameter", "parameter");
+
+ tomcat.start();
+ }
+@@ -1205,6 +1239,24 @@ public abstract class Http2TestBase exte
+ }
+ }
+
++
++ static class ParameterServlet extends HttpServlet {
++
++ private static final long serialVersionUID = 1L;
++
++ @Override
++ protected void doPost(HttpServletRequest req, HttpServletResponse resp)
++ throws ServletException, IOException {
++
++ Map params = req.getParameterMap();
++
++ resp.setContentType("text/plain");
++ resp.setCharacterEncoding("UTF-8");
++
++ resp.getWriter().print(params.size());
++ }
++ }
++
+
+ static class SettingValue {
+ private final int setting;
+diff -Nurp apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/TestHttp2Timeouts.java apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/TestHttp2Timeouts.java
+--- apache-tomcat-9.0.10-src/test/org/apache/coyote/http2/TestHttp2Timeouts.java 2019-06-09 20:45:15.323000000 -0400
++++ apache-tomcat-9.0.10-src-bak/test/org/apache/coyote/http2/TestHttp2Timeouts.java 2019-06-09 20:57:22.652000000 -0400
+@@ -26,7 +26,6 @@ public class TestHttp2Timeouts extends H
+ @Before
+ public void http2Connect() throws Exception {
+ super.http2Connect();
+- sendSettings(0, false, new SettingValue(Setting.INITIAL_WINDOW_SIZE.getId(), 0));
+ }
+
+
+@@ -36,7 +35,7 @@ public class TestHttp2Timeouts extends H
+ */
+ @Test
+ public void testClientWithEmptyWindow() throws Exception {
+- sendSimpleGetRequest(3);
++ sendSettings(0, false, new SettingValue(Setting.INITIAL_WINDOW_SIZE.getId(), 0));
+
+ // Settings
+ parser.readFrame(false);
+@@ -57,6 +56,7 @@ public class TestHttp2Timeouts extends H
+ */
+ @Test
+ public void testClientWithEmptyWindowLargeResponse() throws Exception {
++ sendSettings(0, false, new SettingValue(Setting.INITIAL_WINDOW_SIZE.getId(), 0));
+ sendLargeGetRequest(3);
+
+ // Settings
+@@ -70,4 +70,36 @@ public class TestHttp2Timeouts extends H
+ Assert.assertEquals("3-RST-[11]\n", output.getTrace());
+ }
+
++ /*
++ * Timeout with app reading request body directly.
++ */
++ @Test
++ public void testClientPostsNoBody() throws Exception {
++ sendSimplePostRequest(3, null, false);
++
++ // Headers
++ parser.readFrame(false);
++ output.clearTrace();
++
++ parser.readFrame(false);
++
++ Assert.assertEquals("3-RST-[11]\n", output.getTrace());
++ }
++
++
++ /*
++ * Timeout with app processing parameters.
++ */
++ @Test
++ public void testClientPostsNoParameters() throws Exception {
++ sendParameterPostRequest(3, null, null, 10, false);
++
++ // Headers
++ parser.readFrame(false);
++ output.clearTrace();
++
++ parser.readFrame(false);
++
++ Assert.assertEquals("3-RST-[11]\n", output.getTrace());
++ }
+ }
diff --git a/CVE-2019-0199-4.patch b/CVE-2019-0199-4.patch
new file mode 100644
index 0000000..78e7858
--- /dev/null
+++ b/CVE-2019-0199-4.patch
@@ -0,0 +1,38 @@
+--- tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:14 1852700
++++ tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:18 1852701
+@@ -41,9 +41,9 @@
+
+ public class Http2Protocol implements UpgradeProtocol {
+
+- static final long DEFAULT_READ_TIMEOUT = 10000;
+- static final long DEFAULT_WRITE_TIMEOUT = 10000;
+- static final long DEFAULT_KEEP_ALIVE_TIMEOUT = -1;
++ static final long DEFAULT_READ_TIMEOUT = 5000;
++ static final long DEFAULT_WRITE_TIMEOUT = 5000;
++ static final long DEFAULT_KEEP_ALIVE_TIMEOUT = 20000;
+ static final long DEFAULT_STREAM_READ_TIMEOUT = 20000;
+ static final long DEFAULT_STREAM_WRITE_TIMEOUT = 20000;
+ // The HTTP/2 specification recommends a minimum default of 100
+--- tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:14 1852700
++++ tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:18 1852701
+@@ -329,9 +329,16 @@
+ }
+ }
+ }
+- // No more frames to read so switch to the keep-alive
+- // timeout.
+- socketWrapper.setReadTimeout(protocol.getKeepAliveTimeout());
++
++ if (activeRemoteStreamCount.get() == 0) {
++ // No streams currently active. Use the keep-alive
++ // timeout for the connection.
++ socketWrapper.setReadTimeout(protocol.getKeepAliveTimeout());
++ } else {
++ // Streams currently active. Individual streams have
++ // timeouts so keep the connection open.
++ socketWrapper.setReadTimeout(-1);
++ }
+ } catch (Http2Exception ce) {
+ // Really ConnectionException
+ if (log.isDebugEnabled()) {
+
diff --git a/CVE-2019-0199-5.patch b/CVE-2019-0199-5.patch
new file mode 100644
index 0000000..a21d1a3
--- /dev/null
+++ b/CVE-2019-0199-5.patch
@@ -0,0 +1,143 @@
+--- tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:18 1852701
++++ tomcat/java/org/apache/coyote/http2/Http2Protocol.java 2019/02/01 10:28:22 1852702
+@@ -54,6 +54,8 @@
+ // This default is defined by the HTTP/2 specification
+ static final int DEFAULT_INITIAL_WINDOW_SIZE = (1 << 16) - 1;
+
++ static final int DEFAULT_OVERHEAD_COUNT_FACTOR = 1;
++
+ private static final String HTTP_UPGRADE_NAME = "h2c";
+ private static final String ALPN_NAME = "h2";
+ private static final byte[] ALPN_IDENTIFIER = ALPN_NAME.getBytes(StandardCharsets.UTF_8);
+@@ -79,6 +81,8 @@
+ private int maxHeaderSize = Constants.DEFAULT_MAX_HEADER_SIZE;
+ private int maxTrailerCount = Constants.DEFAULT_MAX_TRAILER_COUNT;
+ private int maxTrailerSize = Constants.DEFAULT_MAX_TRAILER_SIZE;
++ private int overheadCountFactor = DEFAULT_OVERHEAD_COUNT_FACTOR;
++
+ private boolean initiatePingDisabled = false;
+ private boolean useSendfile = true;
+ // Compression
+@@ -306,6 +310,16 @@
+ }
+
+
++ public int getOverheadCountFactor() {
++ return overheadCountFactor;
++ }
++
++
++ public void setOverheadCountFactor(int overheadCountFactor) {
++ this.overheadCountFactor = overheadCountFactor;
++ }
++
++
+ public void setInitiatePingDisabled(boolean initiatePingDisabled) {
+ this.initiatePingDisabled = initiatePingDisabled;
+ }
+--- tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:18 1852701
++++ tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:22 1852702
+@@ -30,6 +30,7 @@
+ import java.util.concurrent.ConcurrentHashMap;
+ import java.util.concurrent.ConcurrentLinkedQueue;
+ import java.util.concurrent.atomic.AtomicInteger;
++import java.util.concurrent.atomic.AtomicLong;
+ import java.util.concurrent.atomic.AtomicReference;
+
+ import javax.servlet.http.WebConnection;
+@@ -139,6 +140,9 @@
+ private AtomicInteger streamConcurrency = null;
+ private Queue queuedRunnable = null;
+
++ // Track 'overhead' frames vs 'request/response' frames
++ private final AtomicLong overheadCount = new AtomicLong(-10);
++
+
+ Http2UpgradeHandler(Http2Protocol protocol, Adapter adapter, Request coyoteRequest) {
+ super (STREAM_ID_ZERO);
+@@ -330,6 +334,10 @@
+ }
+ }
+
++ if (overheadCount.get() > 0) {
++ throw new ConnectionException("Too much overhead", Http2Error.ENHANCE_YOUR_CALM);
++ }
++
+ if (activeRemoteStreamCount.get() == 0) {
+ // No streams currently active. Use the keep-alive
+ // timeout for the connection.
+@@ -638,6 +646,9 @@
+ log.debug(sm.getString("upgradeHandler.writeBody", connectionId, stream.getIdentifier(),
+ Integer.toString(len)));
+ }
++
++ reduceOverheadCount();
++
+ // Need to check this now since sending end of stream will change this.
+ boolean writeable = stream.canWrite();
+ byte[] header = new byte[9];
+@@ -1193,6 +1204,16 @@
+ }
+
+
++ private void reduceOverheadCount() {
++ overheadCount.decrementAndGet();
++ }
++
++
++ private void increaseOverheadCount() {
++ overheadCount.addAndGet(getProtocol().getOverheadCountFactor());
++ }
++
++
+ // ----------------------------------------------- Http2Parser.Input methods
+
+ @Override
+@@ -1247,6 +1268,7 @@
+
+ @Override
+ public ByteBuffer startRequestBodyFrame(int streamId, int payloadSize) throws Http2Exception {
++ reduceOverheadCount();
+ Stream stream = getStream(streamId, true);
+ stream.checkState(FrameType.DATA);
+ stream.receivedData(payloadSize);
+@@ -1291,6 +1313,8 @@
+ // determines if a new stream is created or if this stream is ignored.
+ checkPauseState();
+
++ reduceOverheadCount();
++
+ if (connectionState.get().isNewStreamAllowed()) {
+ Stream stream = getStream(streamId, false);
+ if (stream == null) {
+@@ -1340,6 +1364,9 @@
+ throw new ConnectionException(sm.getString("upgradeHandler.dependency.invalid",
+ getConnectionId(), Integer.valueOf(streamId)), Http2Error.PROTOCOL_ERROR);
+ }
++
++ increaseOverheadCount();
++
+ Stream stream = getStream(streamId, false);
+ if (stream == null) {
+ stream = createRemoteStream(streamId);
+@@ -1384,6 +1411,9 @@
+
+ @Override
+ public void setting(Setting setting, long value) throws ConnectionException {
++
++ increaseOverheadCount();
++
+ // Special handling required
+ if (setting == Setting.INITIAL_WINDOW_SIZE) {
+ long oldValue = remoteSettings.getInitialWindowSize();
+@@ -1425,6 +1455,9 @@
+
+ @Override
+ public void pingReceive(byte[] payload, boolean ack) throws IOException {
++ if (!ack) {
++ increaseOverheadCount();
++ }
+ pingManager.receivePing(payload, ack);
+ }
+
+
diff --git a/CVE-2019-0199-6.patch b/CVE-2019-0199-6.patch
new file mode 100644
index 0000000..ef1ed8d
--- /dev/null
+++ b/CVE-2019-0199-6.patch
@@ -0,0 +1,51 @@
+--- tomcat/webapps/docs/config/http2.xml 2019/02/01 10:28:22 1852702
++++ tomcat/webapps/docs/config/http2.xml 2019/02/01 10:28:26 1852703
+@@ -125,9 +125,9 @@
+
+
+ The time, in milliseconds, that Tomcat will wait between HTTP/2 frames
+- before closing the connection. Negative values will be treated as an
+- infinite timeout. If not specified, a default value of -1
+- will be used.
++ when there is no active Stream before closing the connection. Negative
++ values will be treated as an infinite timeout. If not specified, a default
++ value of 20000 will be used.
+
+
+
+@@ -192,7 +192,24 @@
+ The time, in milliseconds, that Tomcat will wait for additional data
+ when a partial HTTP/2 frame has been received. Negative values will be
+ treated as an infinite timeout. If not specified, a default value of
+- 10000 will be used.
++ 5000 will be used.
++
++
++
++ The time, in milliseconds, that Tomcat will wait for additional data
++ frames to arrive for the stream when an application is performing a
++ blocking I/O read and additional data is required. Negative values will be
++ treated as an infinite timeout. If not specified, a default value of
++ 20000 will be used.
++
++
++
++ The time, in milliseconds, that Tomcat will wait for additional window
++ update frames to arrive for the stream and/or conenction when an
++ application is performing a blocking I/O write and the stream and/or
++ connection flow control window is too small for the write to complete.
++ Negative values will be treated as an infinite timeout. If not specified,
++ a default value of 20000 will be used.
+
+
+
+@@ -204,7 +221,7 @@
+ The time, in milliseconds, that Tomcat will wait to write additional
+ data when an HTTP/2 frame has been partially written. Negative values will
+ be treated as an infinite timeout. If not specified, a default value of
+- 10000 will be used.
++ 5000 will be used.
+
+
+
+
diff --git a/CVE-2019-0199-7.patch b/CVE-2019-0199-7.patch
new file mode 100644
index 0000000..0369108
--- /dev/null
+++ b/CVE-2019-0199-7.patch
@@ -0,0 +1,32 @@
+diff -Nurp apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java
+--- apache-tomcat-9.0.10-src/java/org/apache/coyote/http2/Stream.java 2019-06-09 20:59:53.027000000 -0400
++++ apache-tomcat-9.0.10-src-bak/java/org/apache/coyote/http2/Stream.java 2019-06-09 21:02:31.878000000 -0400
+@@ -211,7 +211,12 @@ class Stream extends AbstractStream impl
+ }
+ try {
+ if (block) {
+- wait(handler.getProtocol().getStreamWriteTimeout());
++ long writeTimeout = handler.getProtocol().getStreamWriteTimeout();
++ if (writeTimeout < 0) {
++ wait();
++ } else {
++ wait(writeTimeout);
++ }
+ windowSize = getWindowSize();
+ if (windowSize == 0) {
+ String msg = sm.getString("stream.writeTimeout");
+@@ -889,7 +894,12 @@ class Stream extends AbstractStream impl
+ log.debug(sm.getString("stream.inputBuffer.empty"));
+ }
+
+- inBuffer.wait(handler.getProtocol().getStreamReadTimeout());
++ long readTimeout = handler.getProtocol().getStreamReadTimeout();
++ if (readTimeout < 0) {
++ inBuffer.wait();
++ } else {
++ inBuffer.wait(readTimeout);
++ }
+
+ if (reset) {
+ throw new IOException(sm.getString("stream.inputBuffer.reset"));
+
diff --git a/CVE-2019-0199-8.patch b/CVE-2019-0199-8.patch
new file mode 100644
index 0000000..f921ed2
--- /dev/null
+++ b/CVE-2019-0199-8.patch
@@ -0,0 +1,24 @@
+--- tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:30 1852704
++++ tomcat/java/org/apache/coyote/http2/Http2UpgradeHandler.java 2019/02/01 10:28:34 1852705
+@@ -335,7 +335,9 @@
+ }
+
+ if (overheadCount.get() > 0) {
+- throw new ConnectionException("Too much overhead", Http2Error.ENHANCE_YOUR_CALM);
++ throw new ConnectionException(
++ sm.getString("upgradeHandler.tooMuchOverhead", connectionId),
++ Http2Error.ENHANCE_YOUR_CALM);
+ }
+
+ if (activeRemoteStreamCount.get() == 0) {
+--- tomcat/java/org/apache/coyote/http2/LocalStrings.properties 2019/02/01 10:28:30 1852704
++++ tomcat/java/org/apache/coyote/http2/LocalStrings.properties 2019/02/01 10:28:34 1852705
+@@ -141,6 +141,7 @@
+ upgradeHandler.stream.notWritable=Connection [{0}], Stream [{1}], This stream is not writable
+ upgradeHandler.stream.old=A new remote stream ID of [{0}] was requested but the most recent stream was [{1}]
+ upgradeHandler.tooManyRemoteStreams=The client attempted to use more than [{0}] active streams
++upgradeHandler.tooMuchOverhead=Connection [{0}], Too much overhead so the connection will be closed
+ upgradeHandler.unexpectedAck=Connection [{0}], Stream [{1}], A settings acknowledgement was received when not expected
+ upgradeHandler.unexpectedEos=Unexpected end of stream
+ upgradeHandler.upgrade=Connection [{0}], HTTP/1.1 upgrade to stream [1]
+
diff --git a/CVE-2019-0199-9.patch b/CVE-2019-0199-9.patch
new file mode 100644
index 0000000..78c22a1
--- /dev/null
+++ b/CVE-2019-0199-9.patch
@@ -0,0 +1,24 @@
+--- tomcat/webapps/docs/config/http2.xml 2019/02/01 10:28:34 1852705
++++ tomcat/webapps/docs/config/http2.xml 2019/02/01 10:28:38 1852706
+@@ -188,6 +188,20 @@
+ The default value is an empty String (regexp matching disabled).
+
+
++
++ The factor to apply when counting overhead frames to determine if a
++ connection has too high an overhead and should be closed. The overhead
++ count starts at -10. The count is decreased for each
++ data frame sent or received and each headers frame received. The count is
++ increased by the overheadCountFactorfor each setting
++ received, priority frame received and ping received. If the overhead count
++ exceeds zero, the connection is closed. A value of less than
++ 1 disables this protection. In normal usage a value of
++ 3 or more will close the connection before any streams can
++ complete. If not specified, a default value of 1 will be
++ used.
++
++
+
+ The time, in milliseconds, that Tomcat will wait for additional data
+ when a partial HTTP/2 frame has been received. Negative values will be
+
diff --git a/CVE-2019-0221.patch b/CVE-2019-0221.patch
new file mode 100644
index 0000000..cc2c366
--- /dev/null
+++ b/CVE-2019-0221.patch
@@ -0,0 +1,44 @@
+From 15fcd166ea2c1bb79e8541b8e1a43da9c452ceea Mon Sep 17 00:00:00 2001
+From: Mark Thomas
+Date: Mon, 11 Mar 2019 11:33:03 +0000
+Subject: [PATCH] Escape debug output to aid readability
+
+reason: Escape debug output to aid readability, fix CVE CVE-2019-0221
+https://github.com/apache/tomcat/commit/15fcd16
+
+---
+ java/org/apache/catalina/ssi/SSIPrintenv.java | 3 +--
+ webapps/docs/changelog.xml | 3 +++
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/java/org/apache/catalina/ssi/SSIPrintenv.java b/java/org/apache/catalina/ssi/SSIPrintenv.java
+index 97470b2..092542f 100644
+--- a/java/org/apache/catalina/ssi/SSIPrintenv.java
++++ b/java/org/apache/catalina/ssi/SSIPrintenv.java
+@@ -41,8 +41,7 @@ public class SSIPrintenv implements SSICommand {
+ } else {
+ Collection variableNames = ssiMediator.getVariableNames();
+ for (String variableName : variableNames) {
+- String variableValue = ssiMediator
+- .getVariableValue(variableName);
++ String variableValue = ssiMediator.getVariableValue(variableName, "entity");
+ //This shouldn't happen, since all the variable names must
+ // have values
+ if (variableValue == null) {
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index 697cf07..cbd3961 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -52,6 +52,9 @@
+ Expires header as required by HTTP specification
+ (RFC 7231, 7234). (kkolinko)
+
++
++ Encode the output of the SSI printenv command. (markt)
++
+
+
+
+--
+1.8.3.1
+
diff --git a/CVE-2019-10072-1.patch b/CVE-2019-10072-1.patch
new file mode 100644
index 0000000..93ea148
--- /dev/null
+++ b/CVE-2019-10072-1.patch
@@ -0,0 +1,129 @@
+From 7f748eb6bfaba5207c89dbd7d5adf50fae847145 Mon Sep 17 00:00:00 2001
+From: Mark Thomas
+Date: Tue, 30 Apr 2019 22:18:12 +0100
+Subject: [PATCH] Expand HTTP/2 timeout handling to connection window
+ exhaustion on write.
+
+https://github.com/apache/tomcat/commit/7f748eb
+---
+ .../coyote/http2/Http2UpgradeHandler.java | 32 +++++++++++++++++--
+ java/org/apache/coyote/http2/Stream.java | 27 +++++++++-------
+ webapps/docs/changelog.xml | 4 +++
+ 3 files changed, 50 insertions(+), 13 deletions(-)
+
+diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+index 1d8770a..ab0369a 100644
+--- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java
++++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+@@ -794,7 +794,26 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
+ }
+ if (allocation == 0) {
+ try {
+- stream.wait();
++ // Connection level window is empty. Although this
++ // request is for a stream, use the connection
++ // timeout
++ long writeTimeout = protocol.getWriteTimeout();
++ if (writeTimeout < 0) {
++ stream.wait();
++ } else {
++ stream.wait(writeTimeout);
++ }
++ // Has this stream been granted an allocation
++ int[] value = backLogStreams.get(stream);
++ if (value[1] == 0) {
++ // No allocation
++ // Close the connection. Do this first since
++ // closing the stream will raise an exception
++ close();
++ // Close the stream (in app code so need to
++ // signal to app stream is closing)
++ stream.doWriteTimeout();
++ }
+ } catch (InterruptedException e) {
+ throw new IOException(sm.getString(
+ "upgradeHandler.windowSizeReservationInterrupted", connectionId,
+@@ -985,11 +1004,20 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
+
+
+ private void close() {
+- connectionState.set(ConnectionState.CLOSED);
++ ConnectionState previous = connectionState.getAndSet(ConnectionState.CLOSED);
++ if (previous == ConnectionState.CLOSED) {
++ // Already closed
++ return;
++ }
++
+ for (Stream stream : streams.values()) {
+ // The connection is closing. Close the associated streams as no
+ // longer required.
+ stream.receiveReset(Http2Error.CANCEL.getCode());
++ // Release any streams waiting for an allocation
++ synchronized (stream) {
++ stream.notifyAll();
++ }
+ }
+ try {
+ socketWrapper.close();
+diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java
+index 2c4f67e..8b87b12 100644
+--- a/java/org/apache/coyote/http2/Stream.java
++++ b/java/org/apache/coyote/http2/Stream.java
+@@ -219,17 +219,7 @@ class Stream extends AbstractStream implements HeaderEmitter {
+ }
+ windowSize = getWindowSize();
+ if (windowSize == 0) {
+- String msg = sm.getString("stream.writeTimeout");
+- StreamException se = new StreamException(
+- msg, Http2Error.ENHANCE_YOUR_CALM, getIdentifier().intValue());
+- // Prevent the application making further writes
+- streamOutputBuffer.closed = true;
+- // Prevent Tomcat's error handling trying to write
+- coyoteResponse.setError();
+- coyoteResponse.setErrorReported();
+- // Trigger a reset once control returns to Tomcat
+- streamOutputBuffer.reset = se;
+- throw new CloseNowException(msg, se);
++ doWriteTimeout();
+ }
+ } else {
+ return 0;
+@@ -252,6 +242,21 @@ class Stream extends AbstractStream implements HeaderEmitter {
+ }
+
+
++ void doWriteTimeout() throws CloseNowException {
++ String msg = sm.getString("stream.writeTimeout");
++ StreamException se = new StreamException(
++ msg, Http2Error.ENHANCE_YOUR_CALM, getIdentifier().intValue());
++ // Prevent the application making further writes
++ streamOutputBuffer.closed = true;
++ // Prevent Tomcat's error handling trying to write
++ coyoteResponse.setError();
++ coyoteResponse.setErrorReported();
++ // Trigger a reset once control returns to Tomcat
++ streamOutputBuffer.reset = se;
++ throw new CloseNowException(msg, se);
++ }
++
++
+ @Override
+ public final void emitHeader(String name, String value) throws HpackException {
+ if (log.isDebugEnabled()) {
+diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
+index a8abf2d..5665df4 100644
+--- a/webapps/docs/changelog.xml
++++ b/webapps/docs/changelog.xml
+@@ -362,6 +362,10 @@
+
+ Update the internal fork of Commons DBCP 2 to 2.4.0. (markt)
+
++
++ Expand HTTP/2 timeout handling to include connection window exhaustion
++ on write. (markt)
++
+
+
+
+--
+2.19.1
diff --git a/CVE-2019-10072-2.patch b/CVE-2019-10072-2.patch
new file mode 100644
index 0000000..4619c59
--- /dev/null
+++ b/CVE-2019-10072-2.patch
@@ -0,0 +1,28 @@
+From ada725a50a60867af3422c8e612aecaeea856a9a Mon Sep 17 00:00:00 2001
+From: Mark Thomas
+Date: Fri, 3 May 2019 21:52:41 +0100
+Subject: [PATCH] Fix test failures. Handle full allocation case.
+
+https://github.com/apache/tomcat/commit/ada725a
+---
+ java/org/apache/coyote/http2/Http2UpgradeHandler.java | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+index ab0369a..cadae44 100644
+--- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java
++++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+@@ -804,8 +804,10 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
+ stream.wait(writeTimeout);
+ }
+ // Has this stream been granted an allocation
++ // Note: If the stream in not in this Map then the
++ // requested write has been fully allocated
+ int[] value = backLogStreams.get(stream);
+- if (value[1] == 0) {
++ if (value != null && value[1] == 0) {
+ // No allocation
+ // Close the connection. Do this first since
+ // closing the stream will raise an exception
+--
+2.19.1
diff --git a/apache-tomcat-9.0.10-src.tar.gz b/apache-tomcat-9.0.10-src.tar.gz
new file mode 100644
index 0000000000000000000000000000000000000000..017333d42d2fa721d396d2a40ffb10f584cfd7ad
GIT binary patch
literal 5147367
zcmYIv2{@GB8@6ri`@R!dOUM#ghGeM-sgM{%lw_-rW$dzxk|<-Tv?xN9WQ<*Ch%6yv
z2}PMPWQLjd{m%UU-*6{
zT(kUaM{VVV`tKh`3-h41Xp!?D%hnTA5R*)J@aAYz*7yr=Ww4>G$|7uEP@KGeu-P
zO9rL7m>iZ*LM6}wcw!+vOJQiD9(o}JK1@Z|AF$FO_WJFTOIPK)EfklLrTqc_o5dsI
z;_SA*%gFOCCIo!uMHe+7aX-z)I8Hae7kv`(7j9q{g6lW5+T0;!D3PWePQ|k=(P|AQ
z?yu}GNw^3FJmq}=+gsqVN-{lX&!1NiU<-#Lx=nZBVuA?GW7!^~Cd4XATj9P4>oJ?b
zL8rEJj$chkgN0WxTm__!YrL9xg=AC6g@rW%+`@j^=o{8TJo<&=iAQL0#d*}Xi`^r^
z_;5)go{m&ioJY?`8|Da?-+_NVQDQ`df@(Rt<@(9^x*2a|;l?5`IKD~RN8Vyh-aZE$Gk1sdZG&ELn~-4om9X0oPX
zi&r)=Tz!=Eq68aB`qQuQnX+ldF2S?A5i(4DWH>Xr4KCy>*u<(B>|QF*htH(d!g{zp
zn#bu%HjIG9TiB#`5qpiO3sYoj{=saU*mg2@Qc)Ks;Oi?&^$jfhme4}4;Z2IROg>q=
z^hvy84joTN8_CUyd06udo*fSa}
znNP;x$=eEsiYutM_AV}V1r{2c$OI;ksZ4w@f5j2I>u|Ed2RdViUzG&A9go3jP*%1v
zl8KMthu5P@$Z=Hk9ay*)Zf9SjY2UH35G7#>K*F$SLR_8}VBb?g7#}8NqTl~P>3w?=
zp7031mfMS-1kVsyZnL=)KqBbPK$re|KNC09z{rBbTs
zQiFy)mbQY{1$C09^2*P+T%ShXt-WUP1-@YT(|ClbJOd`uLJZ4S&^{ly%$T_8sD*8X
z$%HcW+^Gv5he}!{dMQ4Bkt2E?nz{$ebPK9?6eDHDH9MYMDnO{M_Wk$enpx1lIeCPp%iUe~a
zSGDnK?o8zmVPkoae$tSZ?I|xB?0A+Y5e*^1E^Qd^-m77gJV#4sB-{`@^R_^fxrCyP
z1bJZIk31@NX2jcp(rnEFu)s7Ae#>kCw`{+rqTE6Df&bY&+OKS4DO7=L;Mxlwjt0G+
zs|qsAqEz@POCGEP-cfdajq4MW^j_Wse2MioTTYN^EvU(M?&BBFIbfjVV
z66QJQersB7-vm6FP=KB*GpR2bmMx#htiW~5eDGArES&fg2{tjgix#vMz$8r8zP~>n
z5|PO#hV-d^3k%hU6i^@if(fWV@}joZ1Zh4n(kuc}qwA4%qR=E~XYNqycBXYr45;vWA}DMwh{O_Ay$_=8PfjLs_{X=g=;y
zjIp7gkq(jxci>~}Q)pvzkoNb`9b*jit6*)X1~B_VaigOXe$h-zv{ML1<=au!Y9ZTh
zP^JthTTwU%??F`j1c04;aNj!oY&Y-WF)j?;`4cG;n*={yQ;A^jTS1@J+@xdeiSAJ0
zBX)-`Xs?CsIR?6w7=V<=^b@xgRPDZCL-NPt_$&vpXElj*keNMLpP|H6H3yc8V)#rh
zqsI(lHER1G_5$F%90e)JhRbB^wp!ae<
zp;hH^VJ!E-r%d5wK4Eem7H1EyMA7oN?5LRCmI`5Z=D=|@br&T1X6@XFt9OlebX-8Bn@@6OVuO^u}1Kufx6o2kb3+vBW{5r3AEE;MCVK*nh^M6zVz*ZF!+i?bx8JnX}A
z5}GiyJj7{DQyW;rzGW7JUoLCr@(a+RCOS$5qyV9Trl!Ga^#yIIxk(Wai7i1dE+Q;4
zsdzG4a=rnS$u9}A_CAO_0|&4ig|M0X#-|
zytD~rXS1ehV;DWnyc#W1BEDbfV@plU?x3rBpY;6utC8VLh>Xm~X#14xDrp=oQA0FA>ez%q;fVHe>51x}-2y2xnIHK=e01tmnw1AGiD
zJBGpb2~>h^OU6tRUQyu^3QD6BkG`B7G7s}CpkrYPnOFn37ICMKf?uHG8R*3WzpUzQ
zW)~u3Sm9nWvY6liaRtS;a`-||W4#tY+9(8o4&F=uu=iH>uv3as
zFb-2S1p5^vB*Dir{s$N$r$CpFi1vc-^8NUUz8W95*9{+X@C4wpjo?r_))gn
z*!w_n1?xsw!PYaFn9C3;HeG#sO+}r852NGR6^J2UZiw8-CuRKBK1+KL1#!r<4q#tS
zrM+{EA0Ch?Cm>4~|GOOp`}pm5Dg4KViP~X%jQc~mzSEm%4j!oBqboTPQ3p3cxHG5|
zqE^i!3e<46a2Q#*NJ1If4I(KI$N4~hNkq|Y!4Uf*+Qq@}$~ERpDrRLH^l(pTV$()h
zduN+Pe+?Gi0T|;6J>I!>b3caz?E#=xVCV@b^2TVix9C6gv#vi#)u=-B%f~-zlUt#H
zG7LP(xj}{vxDrIS=S~>|DA~V+QCeGJ(uDJR0Y#64=2?c}Y&zyA30#Olw=y-3+mDk_
zicFxB=NF^TMRvXZt94xBA}MYK%f5|b;Je~H_WHxJroA7#j+T%bB@yI_KCSRJVu{wt
zV(}ks#|Dg?U}C@?R&pM!aC&aGT8>E?Ms{w4_2*H0fQETOYA84$c|Wa_kY{;gVMAB_
z3;Hu@m(iI2pB{RzYTp27O~98yGnXg}X!s0k5@`Yq74YlKh+`+Vi-Ex!uzr&w0!Dzc
z$R|3+FdZC%(0}2#fSXqZiBwvl#H%ibq=B-HEgig8NBy1qR3F%4)^3hC^A_@nBE)
zFDua84Q~`)7U1lrYJX6wg?j)29_Z><)L+9!Gf*lCJ?9bltU6hs#?Pcv<2URV4XMe*
z7NOmwPNV6Q>71aVd4L1~Gl~u98>sx6NiXk%`@|@KPDw*@$3hZRVXFla8nk`%GnumG
z*burSfhiPv2naIbEstFUq*e|{T5|2mwfVucio$o)Hs
z&Des+O!{Oj;AF)KkI?v$>N!_fc?+fjf>^$c`Zj*P!`VU?KGh0I0L(*1);u|xpadT%
zoF}1FDf|D2Ra0f#r)`)RwGQ|epsp?3j{(s=1R%2ne%DlXHTUB%@;r+u6(dy!_XCg;
z8B2fW4$qU2h7?)&^D)CAf#wvKL9`c~BV^u-UFmzaH&5~wrGZXw18!~SMu)VZK6TFc
zI$+Mmu*}qCESi>A3$&{NoZEEshW5y5LBJOd;dlOf-6Qy<8)up-<$n15>3lAG
z91>uIPyspQ&uhO02od-jdm@&O0c_{NgCzqdpo9J?DCchq1SOpO+PnuuWuA~aRqZ>Q
zeFKD<2VGGGZZnJYGpI1Ocn2r1p;gQ0kpqfwLpwnB{mZaOx`opiJh({%lzM(HUnGQT
z!XgD5FTo`G93$nmOb$(b3E}02c%&FaLm2YJkNDNU#&DjcMZn-gP}ES=?((~EEc{=(
zir;=B1feSzkS+_LLEBMXYu>$xele%c7n@6L&@t20XUA2f#DL27YkP{SCG_21!1wQ==f=#Ez6x;auOShP
zI9!FyqRYnE%K>x901QoW87`%xYv2zsp8G7#QLNJ6Tbc@-0U(0sFmVmg$_iG8MGVgL
z{~vEV$B?8SghBrUg7e(aIoVmLjEs$-&_Vzvfa=9NVc$c_7vKTASUTV-1MvCMcpea9
zki{hAC|?1uh4db#7o;ctK-(B(N7a-iw*$g2
zML`k_ju@GQM$rJSPXSyntoa+yyGci-$}*s3gY4)*T9Xu|Nl+lrcG|JDDTXh^aC?&2
zXy``-67zG)3eZUaD(n9FmD1Yt0u&dK0u=4bfT|eUb-?b1))zMEoJ(YEG3a?f5TK`P
z9^bsJrMiuJdZugw5P}riN--Y&27U-ki<%WAAffsBuql~}2R#Wiy0!nv!Tu#|dn`l-
zu=W3+T0lPdtb_S4MqRXqGMKR&!kdm!pesbtHs&NUs4FDw4hel2rozm0{C^dN!NdPO
zqi0)IYcQ((eLIZFfgZrnS$!1b=y+2zvatG%Kc(!}W#gC2v2NmzS|L=MI*Fnn5-S96
zT;Jog1A)Fr!(Ltagvi|8ux5N1PAbMd?c^=W
z9_INv7VN}l_6&*uf84GA%so7T#^D7LA&{ar%X>^0CIc;cm{|_?^I^)|RiFY7?P0=6
zNW>;l9f=s3KTHtRWSd;W{@~rmP5AlSX%_usS?v3d=>kf`3IWMadkb
zs5QY6XL1>O4=iCY)lbJ(cHz;!tV)o^0B+b-)}MilTey{TTq0DQBQLJGKfp
zSX(rTmd@3d3I~`oQ)${Hihy#g46OSK5J=xNP}dY;2ziIuX%+OF457AcIIGZ?<3gjTHL;4x%@@bIN%
z#y+T6WKz%>7`TI7pC)o0e!@^W*leI~MJAY@^uZc{Is%Ud7SOW@Tte1@w`F{Rq2qth
zoSC}};#$aehobg!_cqf98eWtk2qqYgsL>V{vLW07_ztkFpQt2B7Gq3TDXt>I8EDga|nyB
z+=Ne>LcL%taxM;;;0B#i0Tzq0AZepNqC}bL#TR&S50tqO>;f9h!^;bNb9jq=Fb^o7
zVo>{t9?-Ku1(Q*i2f%HBl&99}EMt1n4;3}w)Qe3{zP;!okSP{D@L+w{3mSa|>CX)a
z9O#pCekw4z4}M?-u;U)A6a+ECdYtCc6K9oA1}qxzLqJN0&K?w#-#!iT`a%s-@sNb_
z{sr_asmyodUoN*;meH-d0rq4ABXmvV4a;4!_D?;=cBIp=k#&*BoNC~oQINKbAhGs$
z?r{T7V3Df)Uw6iyZVl9vu@{^Q8l
zhK+d!!g@gIBn%4>Tz9DOWvT)RNd4l3Ywg8_l;N<_bsjJq{hLZ`tPym&hcP&2~UGjW`
z8Bjx@rzU~m8T^SZ0?atsk2cT*amj(`pQ6zKPJhO}zA9t5jUA@pA28Ub666^jEYp8A
zzROYwBpA>%fU38!iLSvaWpFnb=o!JE+Sjo4%v$i8+51oxd|@E#CKYplNM*b=85uWC
z6Iep;V~_xg0py9}3`@5HT%Zds*p=>sQqC({)3IkVfK_XG43hJ&h$&g1@_*Q~U4+G`
z3=@U85t!Gud^@i9jQ)`f&T?Zo5oi)XD?9ngu}N|`z#?23lCXeO>$YrPJ++%uaZDLu%H<{jaS5WJUk2Y%>(yXH4C
z6p$sL8gKk@lw=YmW5EY)usjTT4oyjx*c!8|FQan-&j9f&t8#q!8{G!=a`sa=ua&_><9`<|E$+hoJFsqt8l{@WMgUBNttp2aB#peV@Jr%%EdsD}dme!7tZUwpi4+(08Xnso=58M(67b69U)K
z@u2d-%w36=+;sdJR*%IDZrHgW&kLBk5W_pW%@9j!2iQ+k!3`ks!Az%)?4uv2Rqdju
zu9^2T*xU(7M2dNdjKpYdf;dt%p?8rzz$59R`dx~>9XA!D0c1IsISz}3dbUwsz|UKyMv}hck95P~07clg
zXfe4pG8rrhz``e^ra;u@MnzPaM#cb-L4zTjb8QveY#%eQD}m_}0M@HA+c&oWlR!oT
zljMFX?XO}v5ssng(DrLJ`nIU~WV@L~nb!+m&o%f&5^cDV%yxzNNr2L=}jIL5`9fqu2pbkQ3@)E6ZI&Po(Z!B?l
zBio_}y;&j4lrXtypzyTlGz-NDa22HB?-?U
z0ft)+TsN>i+gM=yg3_$L`QRGgoird1I>89*`g`%*@H)J>jhO@&x6|y^jD^xJ!|23b
z0CmM^d{R0tt{F5@V7daz7(J9{6gUo_dIaeD;vBHduOD`Ye*$I+qFe+yRKZj#9>fXz
zN~5hRW^ZEv<{C$H1IEXvPHmPO7!`Fq)hKEY@@xY32Bf!eoR*oa3KgyZh~T8E@zE9k
zb5lU&C@#%CnPNTm6AlB`iXSccq2oNunIRDOPB7XSula{&Kv+LD-3L{^r@^08-48GS
z@7N|xSRKfGcZTt-PI2_2m@zp(0(jULY^7T54psK-9>V}+YU^0;Af^%Oz=j0sG11&WSNce2Hj-7W(kKr*hG)nm*rbe6>xDX86&X0zMA*>EV
z{41zZ@?reLc+RDNC~)fJo6*60uEB>{bYW3{CXHnvNE3yG
z$&LZL`<#f{Byb!EoHUn++0m6}KLauGHtdJimdGI_0f873q5xJ+EK>&}UpZYs04^=;
zZn}4p6D?kQ!&=YNLCoybmUxMqwX(geyI#lvlak5$SeN@|vxmDe-<;PTaK?X=9XV_;
z65eGX8A?#i^k0x$CMdJcIo(^yefHX5G{U9Q=&SyXogdrpT|zQLtxBH%zFw#0Dc0Q5
z%(O!iZ#i&XD?sH-`(wXz-{zD3t;QUPIO!vuBg^$wzn5iA$A6gY#?EJqi^~Up8vY~t
zen7IV=ebx@S9h~Do=rPCgo-oi@;b7b>Ox|lVK?7j`Z>Xbo`RwZ(MY|uu*Xbt*2Jcl
zzLw*br`D~2;Of984r%TS@0$2L4aNQtFN}y-pk_FB>YkPHwjHXP5Pa=U3#we_LbJOb
zJ7|iB%pU)^-mGCtcPY|yOxJ$U#v=D!#sKe>g;Nn39lj{B^|h+jq&%oPM(8@zuvj#A
z$(25jJ{cvBF#Zd5H!Y5ol3hml>^LGb3L{ou*WDyMT|_a_RZ17~e%q~Q$KQGP`?=mx
z#LoLa+4x$uOQfcwvgczKPe<(c66oH&Svw*X`6hCUg#83epuWOExf6`ScE
zo@hyDzq_~jlyIr-R=CvojM(6dKW?WSNNfW;*A#{||2015_|9@!P*O8At^Lr}Czr67
z8i%FNm8>D8>DQ`E%Cuzy(#&uA1t_%k2hFu(D}7$XU^}(@zg#4<8DUah)XH4t)<pzC$+cAE&L~-c$?`LB#baLZMeqWZJanU>SVlL%r
z>)p}NsKvWw>=#b6o2gV+Ozy;*>=IVb9sFji;rRQkaf8-?U2;s@<`pOYez9YhPQ1G}
zIp<4#WRWX&~E9!wy1LP<(PF0J2+w1z&Dkwq@%)X5ZWF3bq(>`
zyo4`-6;Be|uZ)Am#|^KkMKvkjXs_m%-nK0CLf5?K+OH^R*W1avU2%|2w71q6QJYkv
z)4<#LJ;{0Zqar8rDau#*wzY*LhrW{`FY#j6F{|moG=Hm>?o)D~O*9Z6rANlzr)(UO
z;g6a&yKNBq^cjoByRX3%Ze#jvkzr)w)K>|YPBomlrVPx1((JtOs>P^KJ
zpZ4%6i<;@W>rI@8#`*T^`@k%_a?b8iyE
z16(Y#?So?vxHrnhvBns@`JHr%;Fp3A8T%cl8ya!ON4Y2P;Mi|MZuwh1DfliG!6aEjM3ZzMTi@FGA0OLSHk-aDo;`9+R@$`c
zS=4^pGj(R|3M@AGE1^i!6~4HqiMCc!Y10kga7NAcld?pMKm`jIg4>mDRq5CZp;oMe
z2Z+9#qJf9?gN7YQo^|x(zhQsGiVSu3965zdy)#|=4!SE{v_(~~d?%~ulCE?46uB3{^?O{upy
zFUphmz1=>C%jAgc_1_hR$z1#>Qw&S(A4?GgrMTtNLp$+nezvwDVa}gkKx?#?Y2FQ9
zIh2c6(0tGff}E)LC`s|^H1Jka~b>ES%^@qtd!uo{fS#a&PnB|<_nfb
zb;XuMuA;*USG`>;PGlh#dMDacH9KXv=j+msVxG&oFYM#+R-
zr}C%wKIDFQR7~JGFlJdhtFWzJ&z4a4b>ES+)M}YJRpP3EivBfQ^_Ikk&tFLwn1$9Q
zR?8O)qZdB#NSZPEro7@CjVNScX6w3fLs6uiR%}{4r@ln5BF3CO98lo7{Nl
zQ;HPLsg63mG2y}^Ikjp@F@{NVbs^&87xvKc7V)(9UX}&cHSZ_daXR{C0`CcYBf*uf
z+&1BI`Mmc<1mAzsm2axey&8(1W-;6Q%$aMz`=c>m_+!ya{J+^xqWPkO}+fIz6UC
zSFnJ^-<_K~j0goqKlOR_mxJS>elbfFFd6U%yJZrI^+Z!
zS={Qp-?OlEswPLqdlnPYWv`?V3K|xBA?4(!JdONHK8ZDjM$9}?FC)uA>#R}ynZWUN
zFfu^BxHUd-K55AD?`UFW;J7M
zO?lk{_tu^HDQ{!dv1#Sve`Qrys_$keg)7ggB+`$gM^z0c+jda&6_m&>|L>63*hH;$~|(
zmvZ3R-@Bj03}aaig;sE|4E$o#o=p6!9@>r5&i#p(=<9xWD<+KZ((wvGGhtRAn$+ao
z;m603uB<$KD48~ce+H?F1#&~U#MDq-z%p7~ptyR%Ll7dBQ5Z*lP*Akkb
zaE_;>9S>b+eYj<7?DD0x^)Z=)rdFSRX`=7VN5q#Ig?WLb(52!IbFSAxHB(moTSr{U
z!)DN-j&s&q(FDx1x>qAj9cArug36*&C)EQ3ZtIesJ=Z>}wJTHS(kWHLvFkp4B~zhq
zRlz$+dK|K?8|KdOnwkChPUr^l-HX7tLcHgMF31g+XKm~T+F2@i3tXyb%i{f`o{~f}
z8e?7cTBY(tS0QY2F1;|<4`NB)Mr=oYlFCc4Izo7lSkG$Lv}&>Jy!B+wy-6;zDoK
zJFY8Y(fNs;4~ORAJ3GfK4}3ud_HhV2!XcivKd@=Ob3|VbRciJxp5;U)o3)}b@xE?u
zvaRf^po4)sxUudZ?!&GWb|in2THsfY1yfNjzJq-8p_yF12Ww<`YWa*`Br6MNn~@3k
z+O3O*lX#zqw+Y*PZtq;SyTy$pW4pL`?K%#0>gN1?=Aaz$Q!GOvGuXCtFKwMEM1wO(
z>0OLY*WAsZjuoE+!tS?*Gn{x=pC*r6hPaDcPA6^%HF6wI?(pinFp3k&=RlOQd|;jx
z9{kk2ELRfIf$z``W4ppLbX{U@Q2IdWUVwU
zMMPy~!VEmv!_Vve>-##*;o9R{;w*8D_3DArAN%g*{gC|P&ht9CM_vq3nG}{n+Z$F)
zZNzC?exA=UwcLK}RFP7mE38>zyVt<t}5ocdF-jj$FfFPs~*am
zk{m|%5vtGbJr0;9i`dxWY_VQ9vJXO>#oQ(erDxh-g$k@04GWs`mT9jRt6aysZgC5q
z?WMCUUbCGoC<><2wF7(7QHg4wW49ic)7WV8(jB@x+y-9L(fs)jkjd)Ahdx6qfkM*b
zT1*qao&E-v73`)S?fJIgBI40H@--!OZ_#!;|BzE&8_kN6fk`bo5zoA>Yn!$*@|@F;
zsddA{N~uI?CsDn#irF-Zj!0%YBD8(>Z?xm+lGm0)U0`VF)oJ=a
zjf-kY1LGyqU5dF2gH9UJyY}bX59|ZSMI{UC!T1uBdcNB--5#EC*VB6TdAhfPC_^Kfex;(vwHi4e)oZ$S?QZ5`Fxhdl6mk(LTT~ezbB=
zjay1NV!wD8;?kkk+t=|f#69$rigR2uIDHD+91S9nE5*?7zZ}Vm>1eMq6hac{7;WQu
zb4cii`DK)iAxiLZ^Ki=;f1jffOW2t0&auS2*M9fLYuSSmb!P3X=yF#OigEL6X|H1I
ze$HdsBPI;*-L2q3#BlC<{_98-3Fb*o(O$T|YS^b8>S(Q?CR*{p_@dO2hn_}fli%$p
zejk0mbz9e>>Ic`*{Cg4R<+pILQ2;@FZHypQc0!p)cijN(m1VUkzQIDel?l-gs-h
z!>C6-U8vIdx4T=_lx1E@i$vr;uQ<*aq2?o-1@XLz3QS9nYu?-xITYM)Aq8_@m)PC>
zK&j~xa5B)poqr|ork5fgt|l>W!c4$MKItYusMRBrV9-%R$`^P+U$+P!Xfc}oF>QC$hBv9jtP^x;3-Y0<=Xjo=qz|boT~g4zCy{u3AEzY5
zy?dAg#g_NN=}-Ill%rzSLAWj4fiIRE3cEzb!45@<&mpWw_Lvc$1){8nlP$G5n7c&R
zU)_7*!GR;ww5N_h`=|M#Q-pbb0Xd-(Ct^&+ld(>7sh0&UOlq{c!A9d{#+JXZj$Mx5{`Qfr
zyreLN!iVAB>T-wzB{ShJg(M@@-!0x#tJOaTJAdv4R`U;TG5?boLzIm2Vdy-iins*6
za1*x1e>tPy#|ekj4Z51&KFTV2d~9D}aY0%s|J)AobfB|hfkh}M0yk$>SLui4rIY3#)D_zR-6!GUV9FagY!?7q
z-C^I0i5Do#4H?W*Ot#}x3*F+^IVp25mG|=Jc^tacrg-BQdnL~^RM6?(NA9(sf{JYt
zzy6;0?O|DCTeC}F9Fyofv|j&iS?i#|50STCb_g_G$O9L@nCj20G1%br;g$L~&LP&V
z-+h7|k;<#gLw2|vw$<5E*K_4Y5(L$j&Gmx1$LRLF;e@7~IGdwpy9QYtj(-D*fzBec
zkv0O*IC-S%lX<-2AB>#&;R~W7N;16ilCO=Iooy^?{@?=nE7zY-B_dI4YMdzL+leuFr*y#eXWe!?`T`BfOOp0UiC)gxkJl`l`!2S`7)`yez|ci
zl)8KjNwrn~H(_oR_l;!49*?biHFx7v0+m@hmyGFbK9(l%*NwS(`)3d?58wJu4*X__
z?vr)oWJe8=xNJLHBwT59)^8#;iP`v2-`Z*G$P>{q9(!S$t+eDOR&5R!S9JNv=E6qk
ztk@REqg-G63+4?A0u|2d;UDnq;Y--Xe?0H=E-C-b>4kI)`6TZoaDCDK$is_x|8B%4
zj=z+-rN7-|+A2D0JFMJ0rSGq}PXw=(m4^KMl5rUcCrQF
zM0=gW``Tod&)xT;f;oab5-qcTs5f4+y5iQHF!hu9a@Y;$#E<)&cU5QR4sjYq&l6P|
zBUC1#tjOa{d#($rS?3ga&+eOJ*<$~SrWOcsGDG0x3
zKVtIF>Cr8onRWGlvIPp*e{N&4OPAH9DsLE#rQ)`S1v1di=I;$CEX+J5-almZ%D7X6
z%k&d3W@bgI9V+v>^N46j5O~^trrk2I@fB4tE$f7lk$d|9WS^iE)#=>5^~k+qXGyyejXop=e@5ndtA#xr+W)
zt~$rQ7EAw#>ie`}rK=Oan;w&XvXPfP{oQz(HB;z(u9XGy83m_4)h;z}{Z?X_{QZj!
zzq{u6DV$klc~V=C`}%|hB$aQctHsV`<)ao&;+Z$<(k+&f5xp7VXCJym;dhP6dCmJK&R=PI(de#_>=r>hJ#hjK-1s;Oyk2GY0%@bZrM%UMK&z<_*S~2Z&RHku$
z_$;x^Kl8X1%bx)b&pH9U%GaS<12?o-#jY`lD5~_ZghautZcC-cGj;XEvl5s0@S>>?D8HZQ7?Ua+Tq??(iL)|+^c7$?%(BX
zuKR%ddh}pUxuuUt@cXWoNah>77j_kFzqHTKR}Z_y4lHvwl>Bh>5m@|Uk-s|ZD_~^p
z{<`-#;;KaL#-h4cBb1^dCF^0X^W0ycT7(ntDsf3z`68;g@^zDKDJqXV=2JbtW5Yfx
zrL&sQGwO7lvwOSBUNg$$Y$%hvmTkk4C>%oCBWY7sRI^BG^O<=5}ORG@Mjdc9G{
z<6|fBNVZ4cB^wXA$$TwbT7G2UrQ*Pg78xEJfP_6-UW~`CIuSA?APCo(j4JJ@{dBz^
z(U1}Qbtq|1*#1LkO}ZAGc~{<0`J&I;O8WG?sKBBqp}XV$5uKXKAD!$I8Vh1q=nC^%
zou;IFl*2dfWsg+#WXy*cZHen`E!>hH^gv%;Ms)rQHI^0pfbtzZi?5k-cPc(uU=}sD
zKomX6!LfKN%TVF?2i*}t0X69#(QM!B@;{}F`*f-dE}mhYACGt>qhNkM+pu>Z%o>Oy
z1Xo_XVM@Ad8Ke1L{$vib%grUn&YXMcW|7r>tL_6|G%rHAaayv{9RiV;pf~P4QYGz3
zqJ(lG_^MYARcMv&CL&;R!9eW(uu%C&>Cu}-QhHMYMO-=sHxIs<=W`a+no-Cu=2`dk
z3-i7!Bo#^eIG~wrSJ5T5@!r2Ljj2}Z5I>s)D@ugxIP1ejr&dH<<|kIk!P~(>^JJBK
zio$7p>53_A@#hSrsz=)KDV=V2o|ao(XdZtR$5JgK=@^=fs$umWKG`mGQAgOvht0*3
z%eFm_H`{IBp?!<2x~mgxA_qlt0=#*P;U8jzA2slK?BAU9$KU;UvpQxmzI_9-7p-@Q$YKAN0bvtefM4VVXSNBoq(I#Ir>5qPpV{c12l
z9zL~xhev1nm~Mqa$AfzB&KhYW>&wKZzME`s_BTRFdu8&P_trZbt!&A$y}WesS+?8y
zkcE!_o{@V%6|06;M-RQ>b+m8qj9WXZI|B#rt(3-eByxXCu3dO^ecpg)-+5+@+eh`q
zVA-WR%*LE8XST((^E)f#leF0`#m7iyChybn90@)MJDp=yj}N{7*2+${Q1QKX&@%m-
z7(`u<9(iT{)PPI2(T2+T^r=z7J%4ya%zK)Fi-Wc3#m|U#M*W^O%?$Kwizo
zvQ6$x-m;p#eRdIXyNx+NPIR5`s`@rKrs@H+y^{HOz+-wkz^U*be1r!qSH
z-`3(}U9<
zKeY90iWtSB1M(;hCto=6feDtq@3<;k$v=&dE3ix!n
zVdU4lH?Z)H;yv5RveiN~?pzfzfu0+`#}iAz-q;rK*1Xq1#S%Wf`k_#~03RsT_(Xe7
z+pPMGl8;j?hEr2%3iU0C^Um83qEy*F<%v8_8X8fjYw=S0)k~R99Xi{}JML_0vRU_(
zGiO$7#_V9b2GhM$-WMucg&$QSuJercl!vF3c{Tpp=q}E>wOipAZmN{hdB(CXA!0I4
zO6=>d`%$rh_wHhSHxwJg>YQq_oc@&iJsk}UP%7#3wh2t9CMYLG^?9!##M*h~&*#;v
zCTn#?oqHwDd*AyR$7oZYMDc-5^XiFQ%BURl#?Y>K#4X{qb^y+P-q
z7QPeZ=gVkr&teo?trs>^3AS
z(_c)co0O&*jd)N#Ql>+mKU)eJnR9NNy$~roz*S1FIV&K2#iz3IfX(UJgq+%PCAmh2
z_EJdf(0E4B(8ERP!_UpHb4NN~obBEeN}S_NS3Z4$Ee@fO7sF+p%o^YE7`bqih<+_)
zsO7vYm3gs4G(a2S_31;}&tHNMbYETyGJk(~j8ccxT)oWEBUmAw=27I`cbWgGuG8_N
z$^mDYN*U#+SqB~U7oG3vw>75N;x)eev6k*-3b(k~;Xb(>{or9GO0&+v!@WDAxt;gXJp$Rk-{e$PXXd#1H@53^PhAfDgX7y#
z`~+Pisr^o{LO&N@KoF@s+bA8B5T3L2AuX5f{uCBh_RDG69`wtz&b+?y)laq=*HbN}Q;8#6y^n8;^
zo&HRY@qJIvu*7EO8%#G+PFwMbf5_MQWcLVnU)R=ax-x`gPfB8Vm9H}>^Z>hIOWC=o
zBy0X8({BOcr#ZfyaSP-v5;3X!=i_;pvW==fHkcqG#>!1u`DW;Yb+0z^JeP)d`TXM8
zRa>HZtfdoiT|(5N{DHmO1fM$pJZ5q2`lq9iD;1TBK7q)bPMUs__xCP@NMAzJC(vAQ
z;>k>nBD*oID>s7Gm-4^hrm`pj@8^iM!!_<6mi(snttTzNNv|il51d+a@*c}_yhu`;
zIpgDt4u)Nql6n__N!1RsE~43aKE_zq9nBo}l@lkbDCQ(#C3&x`w%~3~)Cnv*;rCtd
zyk1--Vd;MhzI6C1f6TY*dXH8KA?Z84Ma*AnEx3h#ZNe&?-=rGH^M0CM?LT^0bEfaP
zQR+T^;z^l5cJ>vnLJ2VvvDyAizb~Fu{iXP3a@l(F*emjI?tS$RC3H~yNfQuHi9kmj~DzU?8Jl61AGVn#A|jO
z-vK`@f4fIJ1Rc4tNmvySk2u|JdfjK(XtMm{-*a2^^#*Lmk87*XJLiooAL`vHhecB&
z0#^v1EkoUcaAgte_<72syd6C$@7(sFt{@J+OZ$rsMx=??C-m|TIy@>!Rw@eR;*2^}
zLdS$UeLOFEIc1w3_kRFbK&QW)$n(G8t)?2vT?KyS>A}1OVgi_(vZ|uPAr7+WcfjB3
z_kZs-o3F&1>pz#x`_UIY2)!XP}jC{8rH=2;h16O4(V1emFbRb|`%R
z&a+>6sZgFhE2xX2%D6r|-1~GWo{vl72(W|-qz!Gg3zB4^zJ@&jK28Dom(o-px&Xp>
zZv(4M_uTZQw(m4x+Z#|>W56<%Vy6Kpnu=mJlP{-R*=#-EYBs=c87ZA9r88NvYN~s&
z>a2lpX#vgnHz3mY{{T*h?k=DK{dYk?^;>JrcBhBxyYwfut4zBB^Yj8}`
z@9-07M#3pU#M4;-Tr#rE%vj^VSlo%&(nqZTA138`n^%I
z@9qk%c|)t^ir%_$GHIkUMg8jW+O+h`>&&J*y3dE@EjF5SHum6X9G)9I9JmsYmAa!#bygSfmy}p9qz1#jB<(mRa#?`gzO9Jl5k-r~+F=w_a)v;sWEj#0_J2cvtt+oB2x7G!#uGR1KMd#)`;};(@#p14ao2}lh
zu5PRg$&iL__90`qQz4@~=621hvaPP~uPz6hx;Jm!leYc&7uthntG(@3A?owhKwdiIO26ZdPbAxz*JpQCYjbPf
zT;;mp4>P50v__ZPQv19O`ToSscY0RMmgHsYdfgwi?w&H$S$m(k
zwvEeNZrmQVN3(f%UXqOBa5k~j-r%Hv^B~++cG=0QT9>YYwZ)V9bn&n$-<(W0mDNq@yed26+d{D?SeG~ZYi}TzuPSZOVNPK->ZETL
z*CTb)>s*c0!bS7Ew|1YVjd^c4%=Bj+{ptLCH@&(qWy|H&QrI^8Tl>bnU)~o>H~0Je
z-FP|f^`&x4QXAGTb3g6npE{$xbh#;)^V6n1sLhAVyM5E%+Iz{GHihcW?9}!~ac@t$
z*#~*{SgBr4F5LRi>vsCL^6GBVo|)(Siav4m_DC*17B94|bZ2+xZmC-B)P)-8{`1xS
zAT!()-K;d8+t*LSnq{6igDQAiIny`lrRg%O-QT+P>zY0-UzQ%P%ZpwkHL)|osU-;Wzl@--ee|DyLx?jcYZGoTE@=lc`dy#$=Tz6XMERa%=Rbq
zbXzF4#&@~?mDz4@ws-JAf$C#nvK$okyLBdKEHbs*;^1V}_ts^1+wadFXUqFd#&O0c
zopMLX*;(P-Hf}G6*{QAPwvYAEWi4Hm$AgRQc)G~$vL{)ke{Yq5v(*5mnxG2~+joh@Y>w{Xi1}Lk}tKHh5QyR1!
zqc(K$qye*_*|v(A^ms2^HPhZQJ*ZmOtzJtmIn(O?L>m{^!``%X_vFo#>h!jH*(kQv
z;wW7*nirGIDmxw(JnPBJFS~}Y+5Yi|@JG5L4X{3H_8RYKBNELhWwQB3x?C(5OSNhd
zsm3!&I?HCo3r#l9TCgIHqbp+FfD61omoo+a@JsyLMfj%_`qMvVOYl4&*cPzDiA$wC
z+olh!wv7bzWEYCT^XuS
z#aLf%8&`@x?cM11z+Bwlo=jUE+aD|k=FoW@Zq3~Mu6vR;{HLdj`-{9Vo!;78DfhIz
z%QRO`^`iWEo~@?UOtUkQw1>>oxpOriZn~4%Rl7C0E45m!tyI3aY+a3S+KYBREtK7n
zk=v{1qiXh2mHMsXZdvP>^lr(W7u1UxP+8rl&1K;{-^x7L-Np2(WM=fddUB!OUAWG2v}~Q6TwcyJL)p2`XlG42HEpgv
zWeeTOXmhS*Dh*+nGapy?<@(L_$wqH_Kx90wM)P`iI$2h|*=lgIv9rsDc{^IKSH0PN
z=K8++5H|Z&&XiXA<)q}~EADc!YtNhIi}cN=VP6;T
zm5$qR%U9OqYU^K&=b6UX88$}io5fU@+RFN7B|O|+*!TNdW7@viKa8rDyna~XpI7sK
z(?(yy-znhlOloWO*0$C2o^*BBvxSFS$(Wj5|2|vs`qtvER_j7haR)_3dg#t-1NXc>
z?>4KuNuxUN-d5+$dMl6BZRRAs7CcLCYejk89@MpqN#W+9JgDpClm2~XaB<$R7IRv`
z@9(YZdVYP|*|yf@YI?W6Ek7=so15ybHxe*Q2Qt{it*TqqT}-kIetz5L@tZ9b5$wMsW#
z)z;Uo#UzuT^z58EKVMa(=KXN9D`$qjT&ZO3bor(v46Ya3PVHuzy=#_bw_sjnm*s8o
z;;E#K-1Jo6?ADciBU3$3cM9hjX;{6`H^b@m*qzKrtH!q45Nd;dp*l2fv%NgwWJG|Mfx7BgEvlk3=Va-b8
zi>qPH+sJ0_#Lh~WJ45mZrS5cnH7=J5{>er;xyV$?zyjzD=Y#v^paU$cN&PyVnF^h4
z^|C%}j7ukSc40k~Y_l?{UQ}k8@nvQ(xb~KV+GbbPUDvYj7mdsFcD1hcALf}A7`4U9
zek+(aw@z(TnQdD2%2KHUO;8)_-S5!^&2q7styJq!6J*c8|D+sn$Tm9M`aAc*fBuI5
z`;Wsy%V*?#QT*8j4(e?#OC#lXkKPbU`TBG}+O-{Tb}}=j*4EjNr1NF|Dfjf$yldp^
z)#hVyxE!^+UdNH^jp4=27K&|c=bjjYVrOBi^?ZAFSIUeg-R0fgW?XRn#ofKuzV7Dr
zi}S~cyK?7G&CBKFQJF0zBlozzc7?QRHOq$5Zl5dn)2?mQl$meYC+_0mUI(+Sd6Ap@
z-quX3J#*m#-Cvp3)y@)_JV45Cs>)s%*yF;5I^M6dc2-x^f>x2%?ariGz374&ay}j_
zb$xG*hx^j1T%Q#SYI#(ejvH4_(SE$RX=a7HNnWaNZqxSsDksUS`|8ft9xg6Sww6o@V+&0#=$K^uFRaQ;Y&kK*2kD0RkB(=TbpyclE
zrpxp6^4@FA)qJIOTezR+SA|+`VUOqLbU$nsM{VPB<@)8v@%nz%*l0o?*m^~Kb1^*M
z+C?yVc8zxVabR8DcIMZ!n|irY%$UCOxGNL~>P_Xo>jFnf&fa9@+x%R~-k5@VYxteU
z?&;xHmE_w(_5QB5xX&((DUeQpMn%2Z#wxn`znW_CHpnRGk)a?)*CkES&)t^HnmyRJR~2~f$5Zd@N3_ongw;bbGSCbUIhs)oLT%W!l+v
zwRzWU57+ICxmw()OW}I7upYg>li#N&i|*6Kvz|OB*
zv$eaiGwS`l>yEu^ng1BVz0meBwyV&_UtZ~cXTDL)yd
zL47t@Jr%rkZd`17cMo;t?kT-6-0i+2JmoS~>&i)&7TdeIrZzRZwo13xmGg-^?V8=P
z@W)76PZJ4kEVZX_pAW(+6x|;Q?_8!-l`_>rAiPUwQdvCLOh*^n)>?ZKfBWq>aoF#Q
zFt4%GYoiB)&yM4N@8fTaIlR?BP+;@71&
zovHiGVt8{~?~kU}YU^aQU8g&mxx9I5I*L_%nhM>qEam+5q~|pHwSC$f-|F@HgL7>@
z>ZRGd@pSvxZ$3JA7t70P>*lI?+bnk1mwTh%Z}!_#db$>Lb=7M(hokC)>Ted8n^LLN
zf7&!JF4ASKt>w1+^mVy6op+Y?zUSm8E1&}&MrEbt16@$Iy4S))9hV;;hTfC9Q>%Ml
zS{G)M=}8wb+PS>AzrAx+Z(7uA_M$$?&(bw(zr3kenhzJ!etYHXH(kNiFQ>lTn8$apuF6XT7E`{rSYvkX!
zZrbZuk8Sm~rCjX$tA2jpFSv`{<1m*in6h)T&2AcU=A@?IuBunlYWDHQ9d*=)MoqZV
zS`WbDF9BD0l$m5}!&TN9jLTQ+uHQ0B>*2|^SL^1@QftyycW&Fvjg@;fZ{Ll3PIJ(A
zZiM@uYFU?tzM8jJ`Nh0tc3O9t%E(^p>&N+HW^T27tt>g7ccVT$lOeM&Y57_w)Y#wsTYKJn1V%)$hw!)4}7Y
zed83K8yO)tRo85D3VBhOY@JYR2ESu^i
zy&B&QD|gk)tBpRb3%OAlG`K#SvO9lzkL5~k
zSnX6V4R?4^m|wTYEq5&sh1<%i*zGLxO1fL$mo7@@lij$m8>{ETYxyMiG+CUqs?GF;
ze7&nYcn{urxtMFT&Z}jmpT9csY+dLtYvbZP+pOf(ZCmlr)7ScFR3GOrMm2vmZBMWL
zt1ETgx_g`$<&*r}y{csHWTRMWdA+Oc{;DlVW@)Zn=}u<4Z=76@OE*{5!uF)t&h)PB
zi{?hVNw+$3_VH@24j;;!r&4Y|op%>fc~P4nhf
zT3zPX?dr1A>O5Ue=lvVGq!FEI}xeQM0*$||4E-=&9*bGKy=ds$N(w%X&~#PcWfdwVbtnuVv^+8U{`^Yl<}
z@Ag{FmDNf%*V#6u6VQlV%gB0ANQFVCOSxy6+}w*0=mRdb`!MOk;VyGnmicb)T-yYqC}ylr^vt7dIAzZ?kZ
z>UeOgnceaF0gQ)>qI`RK+g@E)2BV^WKYYsd`~5a>-gMRV%9?7G_K~ZEhVZmI-4=@Zx>Ty>pt{YSp}?8gHDpyY#j)?K#J{aQ@Skt+lmeBPpKb3tQ00|w
zhof@;ey3;e&og6beV0G4-@C1{3>^Di?Wt?-Tf_VXFoxHXTPbeZU7
zX*35S0_4U@tsYT3;+2nLLx;;wDtY|J-w-^RrB~T4ZF6xd!zwk)Cw&wInJ08X9K?tEbCx5bGmtYR>M4>*44cyve{cJz6a^TZg6GoV=esMI58@jgAm1=z
z&UZV!VpS<+&yn?NX{X5ZqO|b@ZO9uL==)8k_`4Q?OgOVICw#^CY$qhO<3~WiIO2l5
zbE^XsPNRmU<(Y&1fpl!Vv?n=7&xzXnd-RcCn_FiC*`xDA)AuCi`+lte>I@_IaTlQD
zc2Bs0=xjJZM~-wJ>%@kG9bdxh(SL94!+X`Am3Z1-@7Hk4X1>frwg;rTx)@X=6!&`31
zyxhZ;1WmReOm>>2u%TBd{rLapf<_ohefe#Q!X9|qa6#dAHIQ6b2>pVE(1nFRtWsbt
z)u2#X_$QEpNipS|25`#)~F>r+Vq=(WlFJWFICY!1FNY6Ps8f)Ge
zTl{{H+=#!g21MQdiHRl1l;t-jdgnykz+0~c;+PP#FE*SuP)DB}$pI>HEWaG+%`Dj(
z4ZVp1TM)fr$*HAMH#&j(7~SZmsrH@<)3NoN{=S9pm)@uSZDQdf4eryZNZMU-YQG)4
zI|)DmiDu`XTI$)GT2mJOt|bhHwO~j!YUCkLn`GrvUjy58U^a;Tg7A$yPNHG=f)y4>
z#3FGQ>eA8Tw9gS@37jTw&-i0!solsR0hu>LZW~{_c_f~bWp#fz^^QE*MvE{_1#Zlz
zAO)W8C@k>aI^M9?Q$}*|A~b8EhF5w+UZAF(dobShH)syQkZ-w`z1K0{na%}7-ZwrW
zJ5AaH@3{?6$~l?6ji)K)EN8EuQ>E-4^DmHyt9$Mh%NXe>lA014+Q7?VIyUp(KD&Ni
z4V1$7;Dipf!a}S=i~Cd8?&&SDUT*c#{974w;#eVF6VJVhVHBSO)zqC_XP?+*6x_ND
z?e#Vm^-$j|b|-YMM<$}|19O+mAduW8;IKJp&s+>xa%e@C0i;Bc(pI#*9hMk`;??#IhRg`~j6sfl!Ed@O-GhFEh^(7{HMJo#;YOZ36xFI0-(s`Zmba;O
ztlq^t%hgfc+%f_SAIsXnApQ)EHkMCm6Zct{0ISR-hyIC)9DQNpw@DYS%+KKcw@&lJ
zXFiZj%arHjQy!ciDBx2CV9%qQxZb5e@rKivT77k8sP&>_=gDre%d)ePcW14V3odAU
zdhYx0L*w7oqnvGjeO*cv0l!i53pxlEx)U6V{D4UiB0&iIp+q@epk3AZ*VJe*MBA5L
zMq~Bbs|z%!awmG|S*|TjYA9
zyH8jMO|VC%Lu6H@pK1gcEY|dK!mwz+?l)4`4Nll0v5b+YFcju#9UNYa#sgWXjCbdE
zV+hfKD3`R-oQL(k>`0`edFiSfAIP&w56$8usWE3x`ff6rX%G}*@){yTS18ccSj&N8
zQB31-lPy5p)&b$UMm>(0{EgdNw|a5|8YV8p(@)MO8=Na+tOKFG*72RvRfqqaL)p$x
ziZ*U&mlq76>2grM&%6-^zSR@Yroq>}?}Cez+t45d9Jeri?Z3RRN>7LOlsR@Nkj_T?
z4jRZJ0?M;&{W7|Mov!HkIqF4wl6h(pc(s|+$4YIATF~kPCI%9+ce|vg&}5?|_W~?5
zNfT%sNxf!&8^J94>}0+zxo7$p7T1gwmpbY^Is-pR`G$T*5pSUvXfZYCg`fC6Rk2P1
zS>5Zk8OR#j=kI(xO{~S!$LB-hr}`;waU&d=l%n+rN;#LyJ_XHUyqZy|1;IW!BVY>^
z_mu96hK1!>iv4jL6|=;sF1O@_PRN3L;!WhXsm}KP++uN!9gnTLYKS|HtiwIKqmocnCxz5-fJNmjx$YA
z-LQ$Lclu=DOVXOCy{bH^S2~YmzB5WrkjF9padiQ_Bb|{;K>q0Vq=e8k-;mum_~PI@
z1=5QBW(;ugrUtv{SR5bUZ>{BUiFS9f$hGJ_98z{G$O$-03MzR}A&>kVd2WO$`MxyL
zLf0`P&&%MCFxk-(+b)4N$opT(6e5655lnPO0h9#qTZ
z$}M{aCm<@CMl|U?V!8*o`TQ(W9Th7uf9xM`Lf21D;JtOgK|}>hsd?RDxDT_p-+G`K
zE(8K`Mw7&_h9YXI)DleTde;;gEkG`)qW!k)TWJrh+c3QF5OPK3+KoIv=61|L+Ov@o_QjSAyKOG9t?V^z)DLvK2
zmWKy*wC2OP
ze}kxhgOOiY!X?$eep})Cf4(?Y;J)q{4}CEL$$rtq9sNQH47s=pPcmP)z#v~RPf}ms
zjedQ%3anN7p9#h@x)ePB#eF&D&_(kl=C2FO?>NTa{JSju_vOdu|9h+6Mb-bzl>hxs
zfBozEdx*u)l>5*6n)$~ZeHXVDAauPq9z)6B&e1QEh(Z)@frx-Z7tp<<
z(iDq*aRSPHAqY=>Q4~dfaTG~>ePJ{PUvGtlzF-!kzrGv&`fl}Kp2Yb#kBIREe!s@?
z+eiFYGbZT2Q~xPr!V7$z{a|%NA}&jA>D!`;Z%6m;hc$(dPVhc)$43%gcfFNrAY6!k
z7vFbN1>TR@zUQhSNqV3fV+kq4Mos9XO?O<)8oQLX`pIy@P$S@O9g({T6A4FiWQ7I!
zOm+ZmUYRsxq%P^J*KI-RlJ*0sWzFqhulMK}bcCDUv^w3KX%+6u&ssfJmEgWBYe8xS
z8st+$TZ3n)XY06-VK=@pIi3UQ+MGX7Q&Y~UJsQQfT?@%JtM!b4hJxi_?07D84Oko~
z396AEF)0ZaJe)A|d{p5(`@bbCEv-1!Zc%>=D;Wz6Ql{QU+5#HOt24_coT7?q
z-Hzzp&!5L!1hm12nuzFetvJ!UZ0@TVX!l5dAH;kUZwV5wm{h>
zgVi+}0q=Ndm)!>Iwd$SNYamL|HWCjFQ`M{-PxwS1Mv!>30A6Cb#h!3p%x(#M`JM8A
zWOk*me7bkowa0feht3~55Jh7D(SgbpqVYL_MeEc%
z*3f0pbpC)9SEyeFkAsR*d$+c`x*lGE)?uemp0RdmZ-Y;Ba+bC(D9nS_=RVB
zWj}1shE^ukS`wHHVH1Zm;Bw&K_3&8q@MjOt?wft~Wk!tWlkVvi^ziqY>3&Ao!*huZ
z0qqJ9&_9V!%L8ZTlRS!pd&Q=C$P6xkJUzuqiTXnauR3;rzJ)g4oLd7JyltbcbPYju
zOvvx)chf))D_tVh^DGsyH}880H_BfX=viRKB^)tSj=jU5HYo9c>JO9T7smLb2bvPt
zDy(=Fq`Bm>RJxxblWXqM9z#AX#-){87s~>~?1fx!;YPk`)Xkm6?S*F;vV8g(%Fo(A
zv7l6b=|H(U;JOT%zH0-rpSg@DV7MeEC~T`lz5cCW7(Jc%%joUFwsB_O!5Vs(WvM?*
zHh0+ZCKbkUTjgtN%0l5jZ@|5e^Dtym^oy2K3Mr&bH@-y9_0P>{^T$utew!+@yO%>1
zkLw9u7psxj-Sq&vcwS=b*PJA?%_S~B$$&M%`=zNkXYLgWdPbd5sLNy>JlC<$74Q6u
z1r^v^KmiDI9+*rMC2|jPnVnfGbh3e!CiCYLMdsD}YYy>>PFzH|80_mK3050>aQj_&
z0t6oRT}Mc#;%kY$D~NP2$f%@0y*ar5{QRF%u#fU^el{c(ub&MS#zQOP&T5l}Spx5u
zI>h38nCxeJAGBaM&6|Q1;ChAkPnUyG_1Wo{)DIZwkf7MHqTJkNYq8L=esD8
z-57jo)}QW}&UZ3x%{;)Y!jy=4_(!3u{k)se{>mEKuF4|8ISH>E_
z@QOrDUatWGcC;|z6`ya9llL{J+m!IFOQ#|~`(^n&5sPcuj@=^(Y#WKhM}4o*w2l
zvm?HWUI4s@@~MIYy4(FrGaffn;wY&!PI?=WxB8$Y(_Qiv-i|GwulEv)TBrDK5s8qV
zuD%lh@&%@4BniW!NBF2RiMvj97uynvLQ;JpG!|jI`Wbpo6a<+N;`qU3iJqvZMAe<0
z0-b8Mh0l@x9%Q6HX-%KtEV}AffJtuE%30GX3iNX(axzeG7S79i=dtywX(o>DTL;L~
zc6e1UC?(E}4wEI*;_piYzs@|mFQQ_iD-&eP?O!?`VFW;3b-&;9=pKoAz
zIqUv&%f@?Z-WYpUaLH^mo2hPE)#t5dD24Jx71pt^G&VBkz5OEX(hgwj&|;@8439*C
zy@xDe9L2h2v9PK34RsRl78c96k$5RE|M|Tj(1t7q{rp{{fwXHsA=0jDhqWn(OM&^b
zcuF#*%Oj=iXY&82HwwjHdgC8G@%?=zxe&&wqik{v98smCYp+OLs!(E^Y^H}*VEAhc
zY}&CqUJ1dB{w}fMT)63bmC^ilmC?2o7XRr3@q?OjgAS^vb15I?3NVH00ig6#p&P_msIiw9XZTRifR2Wv^5)IQy2|}%^jzRzdBH|>@d*$gp_1OXy$Q-6r@mmt
zNwM(ik3$%c@JG=q6So6xqWmqYk`=sq*eR%Gv`}NLaWF4CwZ)1gGeUgp-*JMPIna!2
z;E-ihsB({#AaH)fW29w&7y{vRKZd|K@=VbW4E5I|NH4U)MaLq6Rvey&0+w!HXHE$9
znG+=+noU^z19H!zaVwOf67ZZR%7~?WB5ueZhVTjy_=h2}m`6b1$Q^vMwU6tHQe}_l
z`>FIC;@;5v`=iPcY{TW7DlT5xGcCSuIzUW`Gn_fqfHv6%n=a0`-w)x1a`?};U|8nR
z1tkmaqMBb<#+x3*0Ii)CO|Z%g-s429#ZJhU+cin~qix<(M}$Shyjl=h%B@X{+YnEk
zWdG6u`#l5`>z8$Z3iQ4B;m#Zf8@go|quqh)ca2E8_(gmJYvvW$)X57U?5XkdoX!^|
zur>@Bp4ypC+!d@qcXjd7?O?M^uenp2pL@T==86|>EM`OT5Prdmig7~^UP7BDf#eqi
zG9N!t=cikv)t}v*AR6@Jv-=-(82G`5OZ3m7>=)R(xODwz;`iwyCU081w)uR#vtKE-Gq}Di!A?J6r9(IOl2xdN{83BCTHT&VjmVSW>;E%-*!;yOanyuso2qt+h)bl{dF8`FDE5)-9Bg`r)#
zgNJ8ll?hMO^RvZ+dtr)FV;>@6L4y1I+k|CNUL}wZYn(d$)4`f!$$4
zQh7}r$M^Pt2O%Hc0WoVIiKO+X2@gGC^bJIvv33Bh#Z1IKePLJdUkd0D@C^l18uVcu
zPQ>09>EKB?BkuWCE}zCcTOXTUFXgg%KYRxGhtrfVo%k8vr**QoM%7i1K9TR}`zT=?
zd6t^7<>zzRChPt>ZwG~Vmk9tFjH{tDNE#`*G-6Mm_eur0j6K>8QX9DZUdFa;hQADK
zh>`2}4^75DRNGH<0>0rXxig>0!}&O3L~p=`j9NiE3Yq
zv#~col1`3w+pjqYX=V&0K19|L?Q~}}S!JQ~wZ8k&e~k|T(R~l0bnt+Rd+uW+p;;W<
zkU2j08WSDmx~O8>Lrx8{4|o(
z5j0#{i6^gF%EKy}vi0_4XA9KZt8PhSY1Q0FzHl?**v98{1;-`e?@F7$QZ~Tfl{SB+
zY=FNjZT?Ex0Dn)~?EGIT8{ijdBicm{T5Xr`?!J_SZZ_R0iAE;I@4O!4RRQT2bTi4G
zk?EQCs%Hy-Qf8n!K)nxkiEuYayca6_Nt%L&<7C#-<#-y&a>!{{ulKhXPf)_YLFU-F4cHlovm+N${4nKBxYWKu>fPYrE72k$G|d3!zK
z<_o^B2;Q8haWa)`ujwbBDlo-b7Spj^JKUgXoR6tW3mNPBJlI|ma
zbwf3>zw9N*GU;b{zrD#-PbRA|_uw&yh>!T)syfR>bd-9-;fz2HF)#9pP{({pjnG~w
z=xEBOM>$ES!mROO<>9zS4SO#zNn6=497ID%JVala?Im{#SQQL%NS{pKAMS9IJxDO}
z1_y&4(%j4gja=X#;^i-LYvP^l5STldY$Y5HR(Y68ff$V*AD;WG_OAtcd7>H45@e&eX!AIn14
z+Vns?Hk`3Kcw{W4e&{VpNa;%Hyt*
zX#PGX?MgguVq5pTdgrMWXi~|Ep}>Vw7fzJ~{cy4fIT-KHs4eQ5$wQyVUF;=q?^U
z&ITUkRKn6wa@=QU+JFcxf3q81{$bL;-;I9zJci~x3Yp6li5_&-`p(?HNL|#3;Q;bW
z7+su44y|sXWhi{Mpa8zNGdiVZ(B{BW@t8+;rX7Fy%*8&4@$yajCgJLF)*rwmBO0v2
zbFn6Elx8L1Uo7%w#!FtkoA%+{=I33U+Ofr>w^P~GEG#w8xGXm47-YBs@JXHvM0cOs
z{J6A%kRrrWRtC?|K2y#5Ce8Ip+P$o+S>u_}(%Z4fmML9IS?44ABLu298f^>uR^5ql
zeG5^z`e?f-ZcMyKoVzt{*h1a%TUC~~JbJ!m%CU50>9$c!(A_NoNu?HW%*50Ubg;)0
z%Jv@?)SF9}cW&aa)atk1+kGXs=X*apTa5~scc}FV*V7{jMBt()udFi+dLh8ur*ZQo
z#^eN33$2XGoYxhQ>M2!SPeF*$=5aCIWP?H*Dj*0^gwO=KG(?w7xtQ{SC%X2j;y}Q9
z;i)W?OXbb@x_i=Tr(PKf(nbe+x!?JLF+RLswc>~#0Eu0mJoZ-KS|r`(Tyzdf#sn
zSt6ipsARBC&8>ZenE$|a#|&kGr(EPcSkFyXEfnyuJk%FDCQjM`!>kwhpbE5Cv)=9l
zt8*ZzO&mg!M^KhgOICKv!of54UF{Q$^b|dSD7{lYdPPl7Ok`nwnw9;Ddp2{VMoIN!
zmpS3JCdOz81TpH;8oh_~%$M=`DbIRnXrRFARDDtcdX~lt@A0XHF-d`~IDPIY--hib
z4t{md?p-BkwrYlkq3fcZEi8T!jGzLPH(vSUoK&3NPmvfSy0;*)Q2LIyXny8aFMVd#7oD2kg?yBFW^7e*RL$?2NyJV=7>~;2{EdZ
zF4A3RrG0E4&6cPWmdy=5!@zsb>YFX-#ghIV}#A@Xc1X#x+F?L)rge^zTSxG)r9y`t1LZ@hOr6;+zTg5@$
zs5m_VH^OnZDIH3{UE#KU?%hBQw^pCxg0`utNP_sGa%(U78nGJSqUHV_oc!(;Ka4o`
zc>od!wo(VI7C|L_%X<8l-?#eHz9?MSAoCe{um$U(m_6_L30ld6qCZi!
z=e99}joHJs*8!cZ`(y+k+L|PVJfuQ+Ya6c67gsh!=QqbIiqi$+Y1ZwMY*hQjfHQ9B
ztTOfI^Vr0?=`B=CCTh0J8_#0{&(&tU!OPPU!!E-021U38kY#O3gwHa+E4g!EZr;AX
z0JY48aY0=o+}g6mzT9#C80VbggZK7X?~d)_`vUNo8--N0_Sy2>vlJ2eyRpy+
zUyw!0#M28co;lba%t%4{y$+V*mCbsp-lALTa^MpO;-K^~=W*Dz`GE7MyE>}hJn~%R
z*J$eV&xva&zgmX_iA_bx8szR{e7i%Obr-E@d;=8MPQjeb*fQeYGl<^&e)Jc|N;jgt
z53kpe*>Q(3L4WcU?j5Zc^$}LCK}7Y>{uxWa5p>$~<8)2%4(t5$>dvx4XXVai>d4kf
z84{MY1}9R6A3w>X<4#tWm*l>rf_CWnC6L%zJ5{t4+V#7nKAV9j3tu04=afDaX`=9q
z(R8&pLaKZ2gRM)7)N|75$OAGsMtcLOeEVo}p$3LGZXIJH-7yWI21buW^b;he8ft7A
zjO-5gW0`R+lx=l!D36BLzO&@vvIFlVV0NU5!NBTmctpnJR%Pz-YjNssZ1(PHM=R%f
zditC$q2{^+SaH^gKUgJgb70@0@3OnMy3Rl2f6%ax-3-3NIs2P%&iyf3f9?whq6=_S
z*wtsW3X58X<&Ot{ZrL-n1WJ(K_9XK@r0t?mZNj}Y!H3+ula(4AnFSYL6LRnd@DDwO
z+Gq6Iy6v3sXI=K^PIF2=0{
zeMV0@0Rrb!0bOXQih|_oAaFaZU_D=NsRydcMREJ+$&1xr5jr?IJf}3!nQ;Uk?X%RS
zfblxMoMJB=zjskk{x*KJTsM7hMR1#Z&@3~3j1W;@FZ6MvlJ2N_2RI4Khd&Aj6TKRO
zxuc)qB^aH!EU>rM2_sjm_r5J$(jG+;9aLX
z%Rk=}@)BU8SWe;``-O(&X=a|W9VytvtW2`L)sk`WJL+)~F!1Dx@g3~$b>T=5dw{KR
zSWYa(sFBwO5+hXuE^_3?yZbKJ5LM|#JeTL|Euh|Q>VbnAvJ}+?|H;IAVc+ZrKG2U=
z+{dFVPoHV0aDMpRZNDKybb4-i2!hCGn2Vs8$S)d@L-g4*PtJ3u0xm|DX
zZZ4
z8_pmCR)yyG(NU${9RKaIyUSHD68%{*Mt*N6hmb!n^RoWm|EK$WJ)<=#zrXk3>wmwq
zuKSBBuL49FT%dV@`E9fRqbjf8>>K~3&Z~Uq&GWm?E0&^S&tj(QE%zb{1x`^5HJo8K
zNd&gC&10DMx`N-wi?cI%Zd~B9UM6O#W_&t$hnR2lX$Aa4TKpuL9ZWEuPYN}lmq45<
zIXkRob?U6z6PWraiv+6=WVINnk_j4c(@dK$CotoZOS;OR;Vx(qE!N`cb;*H$ICr{0
zP>2+!Ld10VPP>7(8F&}R&@9?X5fQ9duMgkUA}{dY2ZOZ4{ejb;s*`eMpkG~Uv^=VW
zo2)I}Cl>DBOyW;~rQeZ9)!?U;tftW`A-oi2e~f~`s1K<-bKe)F1qQc^CmL7SJCHi!
zO+S<_#TRJq9l(eiM%PVTdmKJ0A`u;4GOvb-t&Z4D^gJ@!oTw2WPc%ZcE7!fHWEz;9Im
zsqMO~NFI-!(u2N4=q*tp6&`5Db`KkkGRie2z+