You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2023/10/09 20:30:09 UTC
[tomcat] branch 9.0.x updated (529370e1cc -> 6d1a9fd664)
This is an automated email from the ASF dual-hosted git repository.
markt pushed a change to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
from 529370e1cc Restore i18n string incorrectly removed back in 2011
new 5958324563 Align processing of trailer headers with standard processing
new 44d05d75d6 Improve handling of failures during recycle() methods
new 6d1a9fd664 Improvements to HTTP/2 overhead protection.
The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../catalina/connector/LocalStrings.properties | 1 +
java/org/apache/catalina/connector/Request.java | 7 +--
.../catalina/core/ApplicationHttpRequest.java | 8 +++-
.../apache/catalina/core/LocalStrings.properties | 1 +
.../catalina/core/LocalStrings_cs.properties | 2 +
.../catalina/core/LocalStrings_es.properties | 2 +
.../catalina/core/LocalStrings_fr.properties | 1 +
.../catalina/core/LocalStrings_ja.properties | 1 +
.../catalina/core/LocalStrings_ko.properties | 1 +
.../catalina/core/LocalStrings_zh_CN.properties | 1 +
.../apache/coyote/http11/Http11InputBuffer.java | 8 +++-
.../coyote/http11/filters/ChunkedInputFilter.java | 15 ++++++-
.../coyote/http11/filters/LocalStrings.properties | 2 +
java/org/apache/coyote/http2/Http2AsyncParser.java | 51 ++++++++++++----------
java/org/apache/coyote/http2/Http2Protocol.java | 19 +++++++-
.../apache/coyote/http2/Http2UpgradeHandler.java | 9 +++-
java/org/apache/tomcat/util/buf/B2CConverter.java | 11 ++++-
java/org/apache/tomcat/util/buf/C2BConverter.java | 15 ++++++-
.../apache/tomcat/util/buf/LocalStrings.properties | 3 ++
webapps/docs/changelog.xml | 10 +++++
webapps/docs/config/http2.xml | 9 +++-
21 files changed, 142 insertions(+), 35 deletions(-)
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 03/03: Improvements to HTTP/2 overhead protection.
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 6d1a9fd6642387969e4410b9989c85856b74917a
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Oct 5 20:54:14 2023 +0100
Improvements to HTTP/2 overhead protection.
---
java/org/apache/coyote/http2/Http2AsyncParser.java | 51 ++++++++++++----------
java/org/apache/coyote/http2/Http2Protocol.java | 19 +++++++-
.../apache/coyote/http2/Http2UpgradeHandler.java | 9 +++-
webapps/docs/changelog.xml | 3 ++
webapps/docs/config/http2.xml | 9 +++-
5 files changed, 64 insertions(+), 27 deletions(-)
diff --git a/java/org/apache/coyote/http2/Http2AsyncParser.java b/java/org/apache/coyote/http2/Http2AsyncParser.java
index 3785962f7d..2a6a2b47a6 100644
--- a/java/org/apache/coyote/http2/Http2AsyncParser.java
+++ b/java/org/apache/coyote/http2/Http2AsyncParser.java
@@ -284,36 +284,39 @@ class Http2AsyncParser extends Http2Parser {
readUnknownFrame(streamId, frameTypeId, flags, payloadSize, payload);
}
}
- // See if there is a new 9 byte header and continue parsing if possible
- if (payload.remaining() >= 9) {
- int position = payload.position();
- payloadSize = ByteUtil.getThreeBytes(payload, position);
- frameTypeId = ByteUtil.getOneByte(payload, position + 3);
- frameType = FrameType.valueOf(frameTypeId);
- flags = ByteUtil.getOneByte(payload, position + 4);
- streamId = ByteUtil.get31Bits(payload, position + 5);
- streamException = false;
- if (payload.remaining() - 9 >= payloadSize) {
- continueParsing = true;
- // Now go over frame header
- payload.position(payload.position() + 9);
- try {
- validateFrame(null, frameType, streamId, flags, payloadSize);
- } catch (StreamException e) {
- error = e;
- streamException = true;
- } catch (Http2Exception e) {
- error = e;
- continueParsing = false;
+ if (!upgradeHandler.isOverheadLimitExceeded()) {
+ // See if there is a new 9 byte header and continue parsing if possible
+ if (payload.remaining() >= 9) {
+ int position = payload.position();
+ payloadSize = ByteUtil.getThreeBytes(payload, position);
+ frameTypeId = ByteUtil.getOneByte(payload, position + 3);
+ frameType = FrameType.valueOf(frameTypeId);
+ flags = ByteUtil.getOneByte(payload, position + 4);
+ streamId = ByteUtil.get31Bits(payload, position + 5);
+ streamException = false;
+ if (payload.remaining() - 9 >= payloadSize) {
+ continueParsing = true;
+ // Now go over frame header
+ payload.position(payload.position() + 9);
+ try {
+ validateFrame(null, frameType, streamId, flags, payloadSize);
+ } catch (StreamException e) {
+ error = e;
+ streamException = true;
+ } catch (Http2Exception e) {
+ error = e;
+ continueParsing = false;
+ }
}
}
}
} while (continueParsing);
} catch (RuntimeException | IOException | Http2Exception e) {
error = e;
- }
- if (payload.hasRemaining()) {
- socketWrapper.unRead(payload);
+ } finally {
+ if (payload.hasRemaining()) {
+ socketWrapper.unRead(payload);
+ }
}
}
if (state == CompletionState.DONE) {
diff --git a/java/org/apache/coyote/http2/Http2Protocol.java b/java/org/apache/coyote/http2/Http2Protocol.java
index ff7b7e3860..e9095489a9 100644
--- a/java/org/apache/coyote/http2/Http2Protocol.java
+++ b/java/org/apache/coyote/http2/Http2Protocol.java
@@ -63,8 +63,10 @@ public class Http2Protocol implements UpgradeProtocol {
// Maximum amount of streams which can be concurrently executed over
// a single connection
static final int DEFAULT_MAX_CONCURRENT_STREAM_EXECUTION = 20;
-
+ // Default factor used when adjusting overhead count for overhead frames
static final int DEFAULT_OVERHEAD_COUNT_FACTOR = 10;
+ // Default factor used when adjusting overhead count for reset frames
+ static final int DEFAULT_OVERHEAD_RESET_FACTOR = 50;
// Not currently configurable. This makes the practical limit for
// overheadCountFactor to be ~20. The exact limit will vary with traffic
// patterns.
@@ -98,6 +100,7 @@ public class Http2Protocol implements UpgradeProtocol {
private int maxTrailerCount = Constants.DEFAULT_MAX_TRAILER_COUNT;
private int maxTrailerSize = Constants.DEFAULT_MAX_TRAILER_SIZE;
private int overheadCountFactor = DEFAULT_OVERHEAD_COUNT_FACTOR;
+ private int overheadResetFactor = DEFAULT_OVERHEAD_RESET_FACTOR;
private int overheadContinuationThreshold = DEFAULT_OVERHEAD_CONTINUATION_THRESHOLD;
private int overheadDataThreshold = DEFAULT_OVERHEAD_DATA_THRESHOLD;
private int overheadWindowUpdateThreshold = DEFAULT_OVERHEAD_WINDOW_UPDATE_THRESHOLD;
@@ -344,6 +347,20 @@ public class Http2Protocol implements UpgradeProtocol {
}
+ public int getOverheadResetFactor() {
+ return overheadResetFactor;
+ }
+
+
+ public void setOverheadResetFactor(int overheadResetFactor) {
+ if (overheadResetFactor < 0) {
+ this.overheadResetFactor = 0;
+ } else {
+ this.overheadResetFactor = overheadResetFactor;
+ }
+ }
+
+
public int getOverheadContinuationThreshold() {
return overheadContinuationThreshold;
}
diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
index 22472e87d5..5f92b983b4 100644
--- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
@@ -375,7 +375,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
stream.close(se);
}
} finally {
- if (overheadCount.get() > 0) {
+ if (isOverheadLimitExceeded()) {
throw new ConnectionException(
sm.getString("upgradeHandler.tooMuchOverhead", connectionId),
Http2Error.ENHANCE_YOUR_CALM);
@@ -1422,6 +1422,11 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
}
+ boolean isOverheadLimitExceeded() {
+ return overheadCount.get() > 0;
+ }
+
+
// ----------------------------------------------- Http2Parser.Input methods
@Override
@@ -1701,6 +1706,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
log.debug(sm.getString("upgradeHandler.reset.receive", getConnectionId(), Integer.toString(streamId),
Long.toString(errorCode)));
}
+ increaseOverheadCount(FrameType.RST, getProtocol().getOverheadResetFactor());
AbstractNonZeroStream abstractNonZeroStream = getAbstractNonZeroStream(streamId, true);
abstractNonZeroStream.checkState(FrameType.RST);
if (abstractNonZeroStream instanceof Stream) {
@@ -1834,6 +1840,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
@Override
public void priorityUpdate(int prioritizedStreamID, Priority p) throws Http2Exception {
+ increaseOverheadCount(FrameType.PRIORITY_UPDATE);
AbstractNonZeroStream abstractNonZeroStream = getAbstractNonZeroStream(prioritizedStreamID, true);
if (abstractNonZeroStream instanceof Stream) {
Stream stream = (Stream) abstractNonZeroStream;
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 2f4d6510b6..a589223fd8 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -167,6 +167,9 @@
<fix>
Align validation of HTTP trailer fields with standard fields. (markt)
</fix>
+ <fix>
+ Improvements to HTTP/2 overhead protection. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Jasper">
diff --git a/webapps/docs/config/http2.xml b/webapps/docs/config/http2.xml
index 472359637b..45b1b6a750 100644
--- a/webapps/docs/config/http2.xml
+++ b/webapps/docs/config/http2.xml
@@ -222,7 +222,7 @@
count starts at <code>-10 * overheadCountFactor</code>. The count is
decreased by 20 for each data frame sent or received and each headers frame
received. The count is increased by the <code>overheadCountFactor</code>
- for each setting received, priority frame received and ping received. If
+ for each setting, priority, priority update and ping frame received. If
the overhead count exceeds zero, the connection is closed. A value of less
than <code>1</code> disables this protection. In normal usage a value of
approximately <code>20</code> or higher will close the connection before
@@ -230,6 +230,13 @@
<code>10</code> will be used.</p>
</attribute>
+ <attribute name="overheadResetFactor" required="false">
+ <p>The amount by which the overhead count (see
+ <strong>overheadCountFactor</strong>) will be increased for each reset
+ frame received. If not specified, a default value of <code>50</code> will
+ be used. A value of less than zero will be treated as zero.</p>
+ </attribute>
+
<attribute name="overheadDataThreshold" required="false">
<p>The threshold below which the average payload size of the current and
previous non-final <code>DATA</code> frames will trigger an increase in
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 02/03: Improve handling of failures during recycle() methods
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 44d05d75d696ca10ce251e4e370511e38f20ae75
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Oct 5 20:52:46 2023 +0100
Improve handling of failures during recycle() methods
---
.../org/apache/catalina/connector/LocalStrings.properties | 1 +
java/org/apache/catalina/connector/Request.java | 7 ++++---
java/org/apache/catalina/core/ApplicationHttpRequest.java | 8 +++++++-
java/org/apache/catalina/core/LocalStrings.properties | 1 +
java/org/apache/catalina/core/LocalStrings_cs.properties | 2 ++
java/org/apache/catalina/core/LocalStrings_es.properties | 2 ++
java/org/apache/catalina/core/LocalStrings_fr.properties | 1 +
java/org/apache/catalina/core/LocalStrings_ja.properties | 1 +
java/org/apache/catalina/core/LocalStrings_ko.properties | 1 +
.../apache/catalina/core/LocalStrings_zh_CN.properties | 1 +
java/org/apache/tomcat/util/buf/B2CConverter.java | 11 ++++++++++-
java/org/apache/tomcat/util/buf/C2BConverter.java | 15 ++++++++++++++-
java/org/apache/tomcat/util/buf/LocalStrings.properties | 3 +++
webapps/docs/changelog.xml | 4 ++++
14 files changed, 52 insertions(+), 6 deletions(-)
diff --git a/java/org/apache/catalina/connector/LocalStrings.properties b/java/org/apache/catalina/connector/LocalStrings.properties
index eba56eb075..df1de99f90 100644
--- a/java/org/apache/catalina/connector/LocalStrings.properties
+++ b/java/org/apache/catalina/connector/LocalStrings.properties
@@ -51,6 +51,7 @@ coyoteRequest.attributeEvent=Exception thrown by attributes event listener
coyoteRequest.authenticate.ise=Cannot call authenticate() after the response has been committed
coyoteRequest.changeSessionId=Cannot change session ID. There is no session associated with this request.
coyoteRequest.chunkedPostTooLarge=Parameters were not parsed because the size of the posted data was too big. Because this request was a chunked request, it could not be processed further. Use the maxPostSize attribute of the connector to resolve this if the application should accept large POSTs.
+coyoteRequest.deletePartFailed=Failed to deleted temporary file used for part [{0}]
coyoteRequest.filterAsyncSupportUnknown=Unable to determine if any filters do not support async processing
coyoteRequest.getContextPath.ise=Unable to find match between the canonical context path [{0}] and the URI presented by the user agent [{1}]
coyoteRequest.getInputStream.ise=getReader() has already been called for this request
diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java
index 2305d147f4..e5fb06f152 100644
--- a/java/org/apache/catalina/connector/Request.java
+++ b/java/org/apache/catalina/connector/Request.java
@@ -473,8 +473,9 @@ public class Request implements HttpServletRequest {
for (Part part : parts) {
try {
part.delete();
- } catch (IOException ignored) {
- // ApplicationPart.delete() never throws an IOEx
+ } catch (Throwable t) {
+ ExceptionUtils.handleThrowable(t);
+ log.warn(sm.getString("coyoteRequest.deletePartFailed", part.getName()), t);
}
}
parts = null;
@@ -527,8 +528,8 @@ public class Request implements HttpServletRequest {
asyncSupported = null;
if (asyncContext != null) {
asyncContext.recycle();
+ asyncContext = null;
}
- asyncContext = null;
}
diff --git a/java/org/apache/catalina/core/ApplicationHttpRequest.java b/java/org/apache/catalina/core/ApplicationHttpRequest.java
index aa81c1196d..cc86ba88db 100644
--- a/java/org/apache/catalina/core/ApplicationHttpRequest.java
+++ b/java/org/apache/catalina/core/ApplicationHttpRequest.java
@@ -48,6 +48,7 @@ import org.apache.catalina.connector.RequestFacade;
import org.apache.catalina.util.ParameterMap;
import org.apache.catalina.util.RequestUtil;
import org.apache.catalina.util.URLEncoder;
+import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.buf.B2CConverter;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.http.Parameters;
@@ -618,7 +619,12 @@ class ApplicationHttpRequest extends HttpServletRequestWrapper {
*/
public void recycle() {
if (session != null) {
- session.endAccess();
+ try {
+ session.endAccess();
+ } catch (Throwable t) {
+ ExceptionUtils.handleThrowable(t);
+ context.getLogger().warn(sm.getString("applicationHttpRequest.sessionEndAccessFail"), t);
+ }
}
}
diff --git a/java/org/apache/catalina/core/LocalStrings.properties b/java/org/apache/catalina/core/LocalStrings.properties
index 4d72b24c78..0430811c3f 100644
--- a/java/org/apache/catalina/core/LocalStrings.properties
+++ b/java/org/apache/catalina/core/LocalStrings.properties
@@ -59,6 +59,7 @@ applicationFilterRegistration.nullInitParam=Unable to set initialisation paramet
applicationFilterRegistration.nullInitParams=Unable to set initialisation parameters for filter due to null name and/or value. Name [{0}], Value [{1}]
applicationHttpRequest.fragmentInDispatchPath=The fragment in dispatch path [{0}] has been removed
+applicationHttpRequest.sessionEndAccessFail=Exception triggered ending access to session while recycling request
applicationPushBuilder.methodInvalid=The HTTP method for a push request must be both cacheable and safe but [{0}] is not
applicationPushBuilder.methodNotToken=HTTP methods must be tokens but [{0}] contains a non-token character
diff --git a/java/org/apache/catalina/core/LocalStrings_cs.properties b/java/org/apache/catalina/core/LocalStrings_cs.properties
index 0128dad5e4..81c77bba79 100644
--- a/java/org/apache/catalina/core/LocalStrings_cs.properties
+++ b/java/org/apache/catalina/core/LocalStrings_cs.properties
@@ -24,6 +24,8 @@ applicationDispatcher.specViolation.response=Původní ServletResponse nebo zapo
applicationFilterRegistration.nullInitParams=Není možné nastavit inicializační parametry pro filtr kvůli hodnotě null ve jménu či hodnotě. Jméno [{0}], Hodnota [{1}]
+applicationHttpRequest.sessionEndAccessFail=Výjimka vyvolala ukončení přístupu k session během recykllování dotazu
+
aprListener.initializingFIPS=Inicializace FIPS módu...
containerBase.backgroundProcess.cluster=Výjimka při zpracování procesu na pozadí v clusteru [{0}]
diff --git a/java/org/apache/catalina/core/LocalStrings_es.properties b/java/org/apache/catalina/core/LocalStrings_es.properties
index e4b7e48244..47c1b3ef25 100644
--- a/java/org/apache/catalina/core/LocalStrings_es.properties
+++ b/java/org/apache/catalina/core/LocalStrings_es.properties
@@ -52,6 +52,8 @@ applicationFilterConfig.jmxUnregisterFail=Ha fallado el desregistro JMX para el
applicationFilterRegistration.nullInitParam=No puedo poner el parámetro de inicialización para el filtro debido a un nombre nulo y/o valor. Nombre [{0}], Valor [{1}]
applicationFilterRegistration.nullInitParams=No puedo poner los parámetros de inicialización para el filtro debido a un nombre nulo y/o valor. Nombre [{0}], Valor [{1}]
+applicationHttpRequest.sessionEndAccessFail=Excepción disparada acabando acceso a sesión mientras se reciclaba el requerimiento
+
applicationServletRegistration.setServletSecurity.iae=Se ha especificado restricción Null para el servlet [{0}] desplegado en el contexto con el nombre [{1}]
applicationServletRegistration.setServletSecurity.ise=No se pueden añadir restricciones de seguridad al servlet [{0}] desplegado en el contexto con el nombre [{1}] ya que el contexto ya ha sido inicializado.
diff --git a/java/org/apache/catalina/core/LocalStrings_fr.properties b/java/org/apache/catalina/core/LocalStrings_fr.properties
index a06778a4d6..19248e1b73 100644
--- a/java/org/apache/catalina/core/LocalStrings_fr.properties
+++ b/java/org/apache/catalina/core/LocalStrings_fr.properties
@@ -59,6 +59,7 @@ applicationFilterRegistration.nullInitParam=Impossible de fixer le paramètre d'
applicationFilterRegistration.nullInitParams=Impossible de fixer les paramètres d''initialisation du filtre, à cause d''un nom ou d''une valeur nulle, nom [{0}], valeur [{1}]
applicationHttpRequest.fragmentInDispatchPath=Le fragment dans le chemin de dispatch [{0}] a été enlevé
+applicationHttpRequest.sessionEndAccessFail=Exception lancée durant l'arrêt de l'accès à la session durant le recyclage de la requête
applicationPushBuilder.methodInvalid=La méthode HTTP pour une requête push doit être à la fois être sans danger et pouvoir être mise en cache, mais [{0}] ne correspond pas
applicationPushBuilder.methodNotToken=Les méthodes HTTP doivent être des "token", mais [{0}] contient un caractère invalide dans un token.
diff --git a/java/org/apache/catalina/core/LocalStrings_ja.properties b/java/org/apache/catalina/core/LocalStrings_ja.properties
index 8676762728..77abb407b8 100644
--- a/java/org/apache/catalina/core/LocalStrings_ja.properties
+++ b/java/org/apache/catalina/core/LocalStrings_ja.properties
@@ -59,6 +59,7 @@ applicationFilterRegistration.nullInitParam=NULLの名前や値のためにフ
applicationFilterRegistration.nullInitParams=キー [{0}] または値 [{1}] のいずれかが null のためフィルターの初期化パラメータを設定できません。
applicationHttpRequest.fragmentInDispatchPath=ディスパッチパス [{0}] 中のフラグメントは除去されました
+applicationHttpRequest.sessionEndAccessFail=リクエストの再利用中に行ったセッションへのアクセス終了処理で例外が送出されました。
applicationPushBuilder.methodInvalid=プッシュリクエストの HTTP メソッドはキャッシュ可能、かつ、安全でなければなりません。[{0}] は指定できません。
applicationPushBuilder.methodNotToken=HTTP メソッド [{0}] にトークンとして利用できない文字が含まれています。
diff --git a/java/org/apache/catalina/core/LocalStrings_ko.properties b/java/org/apache/catalina/core/LocalStrings_ko.properties
index dc8de884c8..ef6f975b83 100644
--- a/java/org/apache/catalina/core/LocalStrings_ko.properties
+++ b/java/org/apache/catalina/core/LocalStrings_ko.properties
@@ -59,6 +59,7 @@ applicationFilterRegistration.nullInitParam=이름 또는 값 또는 둘 다 널
applicationFilterRegistration.nullInitParams=널인 이름 또는 값 때문에, 필터의 초기화 파라미터를 설정할 수 없습니다. 이름: [{0}], 값: [{1}]
applicationHttpRequest.fragmentInDispatchPath=디스패치 경로 [{0}](으)로부터 URI fragment를 제거했습니다.
+applicationHttpRequest.sessionEndAccessFail=요청을 참조 해제하는 과정에서, 세션에 대한 접근을 종료시키려 개시하는 중 예외 발생
applicationPushBuilder.methodInvalid=PUSH 요청을 위한 HTTP 메소드는 반드시 캐시 가능하고 안전해야 하는데, [{0}]은(는) 그렇지 않습니다.
applicationPushBuilder.methodNotToken=HTTP 메소드들은 토큰들이어야 하지만, [{0}]은(는) 토큰이 아닌 문자를 포함하고 있습니다.
diff --git a/java/org/apache/catalina/core/LocalStrings_zh_CN.properties b/java/org/apache/catalina/core/LocalStrings_zh_CN.properties
index 6aa649f62c..857e4d8db9 100644
--- a/java/org/apache/catalina/core/LocalStrings_zh_CN.properties
+++ b/java/org/apache/catalina/core/LocalStrings_zh_CN.properties
@@ -60,6 +60,7 @@ applicationFilterRegistration.nullInitParam=由于名称和/或值为空,无
applicationFilterRegistration.nullInitParams=由于name和(或)value为null,无法为过滤器设置初始化参数。name为 [{0}],value为 [{1}]
applicationHttpRequest.fragmentInDispatchPath=调度路径[{0}]中的片段已被删除
+applicationHttpRequest.sessionEndAccessFail=在回收请求时,异常触发了对会话的结束访问。
applicationPushBuilder.methodInvalid=推送请求的HTTP方法必须既可缓存又安全,但是[{0}]不是
applicationPushBuilder.methodNotToken=HTTP方法必须是令牌(token),但 [{0}] 包含非令牌字符
diff --git a/java/org/apache/tomcat/util/buf/B2CConverter.java b/java/org/apache/tomcat/util/buf/B2CConverter.java
index 0522e38763..0e9db17813 100644
--- a/java/org/apache/tomcat/util/buf/B2CConverter.java
+++ b/java/org/apache/tomcat/util/buf/B2CConverter.java
@@ -27,6 +27,9 @@ import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.res.StringManager;
/**
@@ -34,6 +37,7 @@ import org.apache.tomcat.util.res.StringManager;
*/
public class B2CConverter {
+ private static final Log log = LogFactory.getLog(B2CConverter.class);
private static final StringManager sm = StringManager.getManager(B2CConverter.class);
private static final CharsetCache charsetCache = new CharsetCache();
@@ -104,7 +108,12 @@ public class B2CConverter {
* Reset the decoder state.
*/
public void recycle() {
- decoder.reset();
+ try {
+ decoder.reset();
+ } catch (Throwable t) {
+ ExceptionUtils.handleThrowable(t);
+ log.warn(sm.getString("b2cConverter.decoderResetFail", decoder.charset()), t);
+ }
leftovers.position(0);
}
diff --git a/java/org/apache/tomcat/util/buf/C2BConverter.java b/java/org/apache/tomcat/util/buf/C2BConverter.java
index 5cff0f3a78..9c0c34b4c4 100644
--- a/java/org/apache/tomcat/util/buf/C2BConverter.java
+++ b/java/org/apache/tomcat/util/buf/C2BConverter.java
@@ -24,11 +24,19 @@ import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.ExceptionUtils;
+import org.apache.tomcat.util.res.StringManager;
+
/**
* NIO based character encoder.
*/
public final class C2BConverter {
+ private static final Log log = LogFactory.getLog(C2BConverter.class);
+ private static final StringManager sm = StringManager.getManager(C2BConverter.class);
+
private final CharsetEncoder encoder;
private ByteBuffer bb = null;
private CharBuffer cb = null;
@@ -49,7 +57,12 @@ public final class C2BConverter {
* Reset the encoder state.
*/
public void recycle() {
- encoder.reset();
+ try {
+ encoder.reset();
+ } catch (Throwable t) {
+ ExceptionUtils.handleThrowable(t);
+ log.warn(sm.getString("c2bConverter.decoderResetFail", encoder.charset()), t);
+ }
leftovers.position(0);
}
diff --git a/java/org/apache/tomcat/util/buf/LocalStrings.properties b/java/org/apache/tomcat/util/buf/LocalStrings.properties
index 576eea58a8..a9ed4914c6 100644
--- a/java/org/apache/tomcat/util/buf/LocalStrings.properties
+++ b/java/org/apache/tomcat/util/buf/LocalStrings.properties
@@ -16,10 +16,13 @@
asn1Parser.lengthInvalid=Invalid length [{0}] bytes reported when the input data length is [{1}] bytes
asn1Parser.tagMismatch=Expected to find value [{0}] but found value [{1}]
+b2cConverter.decoderResetFail=Failed to reset instance of decoder for character set [{0}]
b2cConverter.unknownEncoding=The character encoding [{0}] is not supported
byteBufferUtils.cleaner=Cannot use direct ByteBuffer cleaner, memory leaking may occur
+c2bConverter.encoderResetFail=Failed to reset instance of encoder for character set [{0}]
+
chunk.overflow=Buffer overflow and no sink is set, limit [{0}] and buffer length [{1}]
encodedSolidusHandling.invalid=The value [{0}] is not recognised
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index f65d154ef9..2f4d6510b6 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -125,6 +125,10 @@
<bug>67472</bug>: Send fewer CORS-related headers when CORS is not
actually being engaged. (schultz)
</fix>
+ <add>
+ Improve handling of failures within <code>recycle()</code> methods.
+ (markt)
+ </add>
</changelog>
</subsection>
<subsection name="Coyote">
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[tomcat] 01/03: Align processing of trailer headers with standard processing
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 59583245639d8c42ae0009f4a4a70464d3ea70a0
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Oct 5 20:51:48 2023 +0100
Align processing of trailer headers with standard processing
---
java/org/apache/coyote/http11/Http11InputBuffer.java | 8 +++++++-
.../apache/coyote/http11/filters/ChunkedInputFilter.java | 15 ++++++++++++++-
.../apache/coyote/http11/filters/LocalStrings.properties | 2 ++
webapps/docs/changelog.xml | 3 +++
4 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/java/org/apache/coyote/http11/Http11InputBuffer.java b/java/org/apache/coyote/http11/Http11InputBuffer.java
index 6558d8b8d8..3721b1b712 100644
--- a/java/org/apache/coyote/http11/Http11InputBuffer.java
+++ b/java/org/apache/coyote/http11/Http11InputBuffer.java
@@ -830,6 +830,12 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler
*/
private HeaderParseStatus parseHeader() throws IOException {
+ /*
+ * Implementation note: Any changes to this method probably need to be echoed in
+ * ChunkedInputFilter.parseHeader(). Why not use a common implementation? In short, this code uses non-blocking
+ * reads whereas ChunkedInputFilter using blocking reads. The code is just different enough that a common
+ * implementation wasn't viewed as practical.
+ */
while (headerParsePos == HeaderParsePosition.HEADER_START) {
// Read new bytes if needed
@@ -972,7 +978,7 @@ public class Http11InputBuffer implements InputBuffer, ApplicationBufferHandler
} else if (prevChr == Constants.CR) {
// Invalid value - also need to delete header
return skipLine(true);
- } else if (chr != Constants.HT && HttpParser.isControl(chr)) {
+ } else if (HttpParser.isControl(chr) && chr != Constants.HT) {
// Invalid value - also need to delete header
return skipLine(true);
} else if (chr == Constants.SP || chr == Constants.HT) {
diff --git a/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java b/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
index 7fe17f7b9d..3e844afb11 100644
--- a/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
+++ b/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
@@ -30,6 +30,7 @@ import org.apache.coyote.http11.Constants;
import org.apache.coyote.http11.InputFilter;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.HexUtils;
+import org.apache.tomcat.util.http.parser.HttpParser;
import org.apache.tomcat.util.net.ApplicationBufferHandler;
import org.apache.tomcat.util.res.StringManager;
@@ -443,6 +444,13 @@ public class ChunkedInputFilter implements InputFilter, ApplicationBufferHandler
private boolean parseHeader() throws IOException {
+ /*
+ * Implementation note: Any changes to this method probably need to be echoed in
+ * Http11InputBuffer.parseHeader(). Why not use a common implementation? In short, this code uses blocking
+ * reads whereas Http11InputBuffer using non-blocking reads. The code is just different enough that a common
+ * implementation wasn't viewed as practical.
+ */
+
Map<String,String> headers = request.getTrailerFields();
byte chr = 0;
@@ -489,6 +497,9 @@ public class ChunkedInputFilter implements InputFilter, ApplicationBufferHandler
if (chr == Constants.COLON) {
colon = true;
+ } else if (!HttpParser.isToken(chr)) {
+ // Non-token characters are illegal in header names
+ throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderName"));
} else {
trailingHeaders.append(chr);
}
@@ -550,7 +561,9 @@ public class ChunkedInputFilter implements InputFilter, ApplicationBufferHandler
if (chr == Constants.CR || chr == Constants.LF) {
parseCRLF(true);
eol = true;
- } else if (chr == Constants.SP) {
+ } else if (HttpParser.isControl(chr) && chr != Constants.HT) {
+ throw new IOException(sm.getString("chunkedInputFilter.invalidTrailerHeaderValue"));
+ } else if (chr == Constants.SP || chr == Constants.HT) {
trailingHeaders.append(chr);
} else {
trailingHeaders.append(chr);
diff --git a/java/org/apache/coyote/http11/filters/LocalStrings.properties b/java/org/apache/coyote/http11/filters/LocalStrings.properties
index 72dc788bc5..3114a87d0a 100644
--- a/java/org/apache/coyote/http11/filters/LocalStrings.properties
+++ b/java/org/apache/coyote/http11/filters/LocalStrings.properties
@@ -24,6 +24,8 @@ chunkedInputFilter.invalidCrlfCRCR=Invalid end of line sequence (CRCR)
chunkedInputFilter.invalidCrlfNoCR=Invalid end of line sequence (No CR before LF)
chunkedInputFilter.invalidCrlfNoData=Invalid end of line sequence (no data available to read)
chunkedInputFilter.invalidHeader=Invalid chunk header
+chunkedInputFilter.invalidTrailerHeaderName=Invalid trailer header name (non-token character in name)
+chunkedInputFilter.invalidTrailerHeaderValue=Invalid trailer header value (control character in value)
chunkedInputFilter.maxExtension=maxExtensionSize exceeded
chunkedInputFilter.maxTrailer=maxTrailerSize exceeded
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 66ed96dd79..f65d154ef9 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -160,6 +160,9 @@
Improve statistics collection for upgraded connections under load.
(remm)
</fix>
+ <fix>
+ Align validation of HTTP trailer fields with standard fields. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Jasper">
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org