[Git][java-team/httpcomponents-core5][master] 6 commits: add back missed nmu changelog entry and patch
Jérôme Charaoui (@lavamind)
gitlab at salsa.debian.org
Sat Aug 8 05:13:19 BST 2026
Jérôme Charaoui pushed to branch master at Debian Java Maintainers / httpcomponents-core5
Commits:
f47f8c90 by Adrian Bunk at 2026-08-07T23:58:43-04:00
add back missed nmu changelog entry and patch
- - - - -
34504ed6 by Jérôme Charaoui at 2026-08-08T00:00:17-04:00
New upstream version 5.4.3
- - - - -
d9a7c287 by Jérôme Charaoui at 2026-08-08T00:00:23-04:00
Update upstream source from tag 'upstream/5.4.3'
Update to upstream version '5.4.3'
with Debian dir 4dab85049a63035f383c305617cc3296546a093e
- - - - -
451a14b5 by Jérôme Charaoui at 2026-08-08T00:05:07-04:00
drop redundant Priority: optional source field
- - - - -
c4372f9a by Jérôme Charaoui at 2026-08-08T00:05:28-04:00
dump Standards-Version, no changes needed
- - - - -
cdf7241e by Jérôme Charaoui at 2026-08-08T00:09:51-04:00
Update changelog for 5.4.3-1 release
- - - - -
25 changed files:
- RELEASE_NOTES.txt
- debian/changelog
- debian/control
- debian/rules
- httpcore5-h2/pom.xml
- httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java
- httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java
- httpcore5-reactive/pom.xml
- httpcore5-testing/pom.xml
- httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1IntegrationTest.java
- httpcore5/pom.xml
- httpcore5/src/main/java/org/apache/hc/core5/http/config/Http1Config.java
- httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/HttpRequestExecutor.java
- httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamHandler.java
- httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AbstractAsyncRequesterConsumer.java
- httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AbstractServerExchangeHandler.java
- httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/BasicRequestConsumer.java
- httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/BasicResponseConsumer.java
- httpcore5/src/main/java/org/apache/hc/core5/pool/LaxConnPool.java
- httpcore5/src/main/java/org/apache/hc/core5/pool/RouteSegmentedConnPool.java
- httpcore5/src/main/java/org/apache/hc/core5/pool/StrictConnPool.java
- httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
- httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLManagedBuffer.java
- + httpcore5/src/test/java/org/apache/hc/core5/pool/TestStrictConnPoolLeaseTimeoutRace.java
- pom.xml
Changes:
=====================================
RELEASE_NOTES.txt
=====================================
@@ -1,3 +1,40 @@
+Release 5.4.3
+------------------
+
+This maintenance release fixes several defects and regression reported sicne the previous
+release includin a regression in backpressure handling of async TLS sessions introduced in
+version 5.3.3.
+
+Change Log
+-------------------
+
+* HTTPCORE-796: abort redirected requests during the expect-continue handshake the same
+ way as errors.
+ Contributed by Oleg Kalnichevski <olegk at apache.org>
+
+* Fixed regression in backpressure handling of async TLS sessions. Reverts HTTPCORE-775.
+ Contributed by Ryan Schmitt <rschmitt at apache.org>
+
+* Use max line length of 8192 and max header count of 100 for incoming HTTP/1 messages
+ by default.
+ Contributed by Oleg Kalnichevski <olegk at apache.org>
+
+* Enforce configured HPACK header list size limit upon initialization of HTTP/2
+ connections.
+ Contributed by Arturo Bernal <abernal at apache.org>
+
+* HTTPCORE-774: fixed a race condition caused by concurrent update of the connection input
+ window to the max value (ported from 5.3.x; omitted by mistake).
+ Contributed by Oleg Kalnichevski <olegk at apache.org>
+
+* Ensure async data consumers can avoid NPE if they have been canceled or released from another
+ thread at the same with concurrent data processing.
+ Contributed by Oleg Kalnichevski <olegk at apache.org>
+
+* Fixed connection pool lease timeout race potentially causing pool entry leak (#649).
+ Contributed by Arturo Bernal <abernal at apache.org>
+
+
Release 5.4.2
------------------
=====================================
debian/changelog
=====================================
@@ -1,3 +1,14 @@
+httpcomponents-core5 (5.4.3-1) unstable; urgency=medium
+
+ * Team upload.
+ * New upstream version 5.4.3, fixing CVE-2026-54399 and CVE-2026-54428
+ (Closes: #1141387)
+ * add back missed nmu changelog entry and patch (Closes: #1143144)
+ * drop redundant Priority: optional source field
+ * dump Standards-Version, no changes needed
+
+ -- Jérôme Charaoui <jerome at riseup.net> Sat, 08 Aug 2026 00:05:46 -0400
+
httpcomponents-core5 (5.4.2-2) unstable; urgency=medium
* Team upload.
@@ -6,6 +17,13 @@ httpcomponents-core5 (5.4.2-2) unstable; urgency=medium
-- Jérôme Charaoui <jerome at riseup.net> Thu, 30 Jul 2026 10:19:02 -0400
+httpcomponents-core5 (5.4.2-1.1) unstable; urgency=medium
+
+ * Non-maintainer upload.
+ * Fix the timestamp of NOTICE.txt. (Closes: #1134206)
+
+ -- Adrian Bunk <bunk at debian.org> Sun, 31 May 2026 14:56:49 +0300
+
httpcomponents-core5 (5.4.2-1) unstable; urgency=medium
* Team upload.
=====================================
debian/control
=====================================
@@ -1,6 +1,5 @@
Source: httpcomponents-core5
Section: java
-Priority: optional
Maintainer: Debian Java Maintainers <pkg-java-maintainers at lists.alioth.debian.org>
Uploaders:
Markus Koschany <apo at debian.org>
@@ -13,7 +12,7 @@ Build-Depends:
libreactive-streams-java,
libslf4j-java,
maven-debian-helper
-Standards-Version: 4.7.3
+Standards-Version: 4.7.4
Vcs-Git: https://salsa.debian.org/java-team/httpcomponents-core5.git
Vcs-Browser: https://salsa.debian.org/java-team/httpcomponents-core5
Homepage: https://hc.apache.org/
=====================================
debian/rules
=====================================
@@ -2,3 +2,7 @@
%:
dh $@
+
+# https://bugs.debian.org/1134206
+execute_before_dh_auto_install:
+ touch -d@${SOURCE_DATE_EPOCH} NOTICE.txt
=====================================
httpcore5-h2/pom.xml
=====================================
@@ -28,7 +28,7 @@
<parent>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5-parent</artifactId>
- <version>5.4.2</version>
+ <version>5.4.3</version>
</parent>
<artifactId>httpcore5-h2</artifactId>
<name>Apache HttpComponents Core HTTP/2</name>
=====================================
httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java
=====================================
@@ -171,8 +171,7 @@ abstract class AbstractH2StreamMultiplexer implements Identifiable, HttpConnecti
this.initInputWinSize = H2Config.INIT.getInitialWindowSize();
this.initOutputWinSize = H2Config.INIT.getInitialWindowSize();
- this.hPackDecoder.setMaxListSize(H2Config.INIT.getMaxHeaderListSize());
-
+ this.hPackDecoder.setMaxListSize(this.localConfig.getMaxHeaderListSize());
this.lowMark = H2Config.INIT.getInitialWindowSize() / 2;
this.streamListener = streamListener;
}
@@ -1492,7 +1491,6 @@ abstract class AbstractH2StreamMultiplexer implements Identifiable, HttpConnecti
@Override
public void update(final int increment) throws IOException {
- incrementInputCapacity(0, connInputWindow, increment);
incrementInputCapacity(id, inputWindow, increment);
}
=====================================
httpcore5-h2/src/test/java/org/apache/hc/core5/http2/impl/nio/TestAbstractH2StreamMultiplexer.java
=====================================
@@ -28,6 +28,7 @@
package org.apache.hc.core5.http2.impl.nio;
import java.io.IOException;
+import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -46,6 +47,7 @@ import org.apache.hc.core5.http.message.BasicHeader;
import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler;
import org.apache.hc.core5.http.nio.AsyncPushConsumer;
import org.apache.hc.core5.http.nio.AsyncPushProducer;
+import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
import org.apache.hc.core5.http.nio.HandlerFactory;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.http.protocol.HttpProcessor;
@@ -62,6 +64,7 @@ import org.apache.hc.core5.http2.frame.FrameFactory;
import org.apache.hc.core5.http2.frame.FrameType;
import org.apache.hc.core5.http2.frame.RawFrame;
import org.apache.hc.core5.http2.frame.StreamIdGenerator;
+import org.apache.hc.core5.http2.hpack.HPackDecoder;
import org.apache.hc.core5.http2.hpack.HPackEncoder;
import org.apache.hc.core5.reactor.ProtocolIOSession;
import org.apache.hc.core5.util.ByteArrayBuffer;
@@ -678,7 +681,7 @@ class TestAbstractH2StreamMultiplexer {
outBuffer.write(continuationFrame3, writableChannel);
Assertions.assertThrows(H2ConnectionException.class, () ->
- streamMultiplexer.onInput(ByteBuffer.wrap(writableChannel.toByteArray())));
+ streamMultiplexer.onInput(ByteBuffer.wrap(writableChannel.toByteArray())));
}
@Test
@@ -946,7 +949,7 @@ class TestAbstractH2StreamMultiplexer {
new BasicHeader(":authority", "example.test"),
new BasicHeader(HttpHeaders.PRIORITY, "u=3,i")
);
- mux.createStream(ch, new PriorityHeaderSender(ch, reqHeaders, true));
+ mux.createStream(ch, new PriorityHeaderSender(ch, reqHeaders, true));
// Drive output so the handler submits
mux.onOutput();
@@ -1069,5 +1072,41 @@ class TestAbstractH2StreamMultiplexer {
Assertions.assertTrue(idxPriUpd >= 0, "PRIORITY_UPDATE should be emitted when NO_RFC7540=1");
}
+ @Test
+ void testHPackDecoderUsesConfiguredMaxHeaderListSizeImmediately() throws Exception {
+ final int maxHeaderListSize = 128;
+
+ final H2Config h2Config = H2Config.custom()
+ .setMaxHeaderListSize(maxHeaderListSize)
+ .build();
+
+ final ProtocolIOSession ioSession = Mockito.mock(ProtocolIOSession.class);
+ final HttpProcessor httpProcessor = Mockito.mock(HttpProcessor.class);
+ final HandlerFactory<AsyncServerExchangeHandler> handlerFactory = Mockito.mock(HandlerFactory.class);
+
+ final ServerH2StreamMultiplexer multiplexer = new ServerH2StreamMultiplexer(
+ ioSession,
+ httpProcessor,
+ handlerFactory,
+ CharCodingConfig.DEFAULT,
+ h2Config);
+
+ final HPackDecoder hPackDecoder = getHPackDecoder(multiplexer);
+
+ Assertions.assertEquals(maxHeaderListSize, getMaxListSize(hPackDecoder));
+ }
+
+ private static HPackDecoder getHPackDecoder(final AbstractH2StreamMultiplexer multiplexer) throws Exception {
+ final Field field = AbstractH2StreamMultiplexer.class.getDeclaredField("hPackDecoder");
+ field.setAccessible(true);
+ return (HPackDecoder) field.get(multiplexer);
+ }
+
+ private static int getMaxListSize(final HPackDecoder hPackDecoder) throws Exception {
+ final Field field = HPackDecoder.class.getDeclaredField("maxListSize");
+ field.setAccessible(true);
+ return field.getInt(hPackDecoder);
+ }
+
}
=====================================
httpcore5-reactive/pom.xml
=====================================
@@ -27,7 +27,7 @@
<parent>
<artifactId>httpcore5-parent</artifactId>
<groupId>org.apache.httpcomponents.core5</groupId>
- <version>5.4.2</version>
+ <version>5.4.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
=====================================
httpcore5-testing/pom.xml
=====================================
@@ -28,7 +28,7 @@
<parent>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5-parent</artifactId>
- <version>5.4.2</version>
+ <version>5.4.3</version>
</parent>
<artifactId>httpcore5-testing</artifactId>
<name>Apache HttpComponents Core Integration Tests</name>
=====================================
httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http1IntegrationTest.java
=====================================
@@ -758,6 +758,9 @@ abstract class Http1IntegrationTest extends HttpIntegrationTest {
@Override
public int write(final ByteBuffer src) throws IOException {
+ if (!channel().isOpen()) {
+ return 0;
+ }
final int chunk;
if (!done) {
lineBuffer.clear();
=====================================
httpcore5/pom.xml
=====================================
@@ -28,7 +28,7 @@
<parent>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5-parent</artifactId>
- <version>5.4.2</version>
+ <version>5.4.3</version>
</parent>
<artifactId>httpcore5</artifactId>
<name>Apache HttpComponents Core HTTP/1.1</name>
=====================================
httpcore5/src/main/java/org/apache/hc/core5/http/config/Http1Config.java
=====================================
@@ -144,8 +144,8 @@ public class Http1Config {
private static final int INIT_BUF_SIZE = 8192;
private static final Timeout INIT_WAIT_FOR_CONTINUE = Timeout.ofSeconds(3);
private static final int INIT_BUF_CHUNK = -1;
- private static final int INIT_MAX_HEADER_COUNT = -1;
- private static final int INIT_MAX_LINE_LENGTH = -1;
+ private static final int INIT_MAX_HEADER_COUNT = 100;
+ private static final int INIT_MAX_LINE_LENGTH = 8192;
private static final int INIT_MAX_EMPTY_LINE_COUNT = 10;
public static class Builder {
=====================================
httpcore5/src/main/java/org/apache/hc/core5/http/impl/io/HttpRequestExecutor.java
=====================================
@@ -183,7 +183,7 @@ public class HttpRequestExecutor {
}
response = null;
continue;
- } else if (status >= HttpStatus.SC_CLIENT_ERROR) {
+ } else if (status >= HttpStatus.SC_REDIRECTION) {
conn.terminateRequest(request);
} else {
conn.sendRequestEntity(request);
=====================================
httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/ClientHttp1StreamHandler.java
=====================================
@@ -234,7 +234,7 @@ class ClientHttp1StreamHandler implements ResourceHolder {
if (status == HttpStatus.SC_CONTINUE || status >= HttpStatus.SC_SUCCESS) {
outputChannel.setSocketTimeout(timeout);
requestState.set(MessageState.BODY);
- if (status < HttpStatus.SC_CLIENT_ERROR) {
+ if (status < HttpStatus.SC_REDIRECTION) {
exchangeHandler.produce(internalDataChannel);
}
}
@@ -243,7 +243,7 @@ class ClientHttp1StreamHandler implements ResourceHolder {
return;
}
if (requestState.get() == MessageState.BODY) {
- if (status >= HttpStatus.SC_CLIENT_ERROR) {
+ if (status >= HttpStatus.SC_REDIRECTION) {
requestState.set(MessageState.COMPLETE);
if (!outputChannel.abortGracefully()) {
keepAlive = false;
=====================================
httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AbstractAsyncRequesterConsumer.java
=====================================
@@ -113,19 +113,27 @@ public abstract class AbstractAsyncRequesterConsumer<T, E> implements AsyncReque
@Override
public final void updateCapacity(final CapacityChannel capacityChannel) throws IOException {
final AsyncEntityConsumer<E> dataConsumer = dataConsumerRef.get();
- dataConsumer.updateCapacity(capacityChannel);
+ if (dataConsumer != null) {
+ dataConsumer.updateCapacity(capacityChannel);
+ } else {
+ capacityChannel.update(Integer.MAX_VALUE);
+ }
}
@Override
public final void consume(final ByteBuffer src) throws IOException {
final AsyncEntityConsumer<E> dataConsumer = dataConsumerRef.get();
- dataConsumer.consume(src);
+ if (dataConsumer != null) {
+ dataConsumer.consume(src);
+ }
}
@Override
public final void streamEnd(final List<? extends Header> trailers) throws HttpException, IOException {
final AsyncEntityConsumer<E> dataConsumer = dataConsumerRef.get();
- dataConsumer.streamEnd(trailers);
+ if (dataConsumer != null) {
+ dataConsumer.streamEnd(trailers);
+ }
}
@Override
=====================================
httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/AbstractServerExchangeHandler.java
=====================================
@@ -174,22 +174,27 @@ public abstract class AbstractServerExchangeHandler<T> implements AsyncServerExc
@Override
public final void updateCapacity(final CapacityChannel capacityChannel) throws IOException {
final AsyncRequestConsumer<T> requestConsumer = requestConsumerRef.get();
- Asserts.notNull(requestConsumer, "Data consumer");
- requestConsumer.updateCapacity(capacityChannel);
+ if (requestConsumer != null) {
+ requestConsumer.updateCapacity(capacityChannel);
+ } else {
+ capacityChannel.update(Integer.MAX_VALUE);
+ }
}
@Override
public final void consume(final ByteBuffer src) throws IOException {
final AsyncRequestConsumer<T> requestConsumer = requestConsumerRef.get();
- Asserts.notNull(requestConsumer, "Data consumer");
- requestConsumer.consume(src);
+ if (requestConsumer != null) {
+ requestConsumer.consume(src);
+ }
}
@Override
public final void streamEnd(final List<? extends Header> trailers) throws HttpException, IOException {
final AsyncRequestConsumer<T> requestConsumer = requestConsumerRef.get();
- Asserts.notNull(requestConsumer, "Data consumer");
- requestConsumer.streamEnd(trailers);
+ if (requestConsumer != null) {
+ requestConsumer.streamEnd(trailers);
+ }
}
@Override
=====================================
httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/BasicRequestConsumer.java
=====================================
@@ -100,19 +100,27 @@ public class BasicRequestConsumer<T> implements AsyncRequestConsumer<Message<Htt
@Override
public void updateCapacity(final CapacityChannel capacityChannel) throws IOException {
final AsyncEntityConsumer<T> dataConsumer = dataConsumerRef.get();
- dataConsumer.updateCapacity(capacityChannel);
+ if (dataConsumer != null) {
+ dataConsumer.updateCapacity(capacityChannel);
+ } else {
+ capacityChannel.update(Integer.MAX_VALUE);
+ }
}
@Override
public void consume(final ByteBuffer src) throws IOException {
final AsyncEntityConsumer<T> dataConsumer = dataConsumerRef.get();
- dataConsumer.consume(src);
+ if (dataConsumer != null) {
+ dataConsumer.consume(src);
+ }
}
@Override
public void streamEnd(final List<? extends Header> trailers) throws HttpException, IOException {
final AsyncEntityConsumer<T> dataConsumer = dataConsumerRef.get();
- dataConsumer.streamEnd(trailers);
+ if (dataConsumer != null) {
+ dataConsumer.streamEnd(trailers);
+ }
}
@Override
=====================================
httpcore5/src/main/java/org/apache/hc/core5/http/nio/support/BasicResponseConsumer.java
=====================================
@@ -104,19 +104,27 @@ public class BasicResponseConsumer<T> implements AsyncResponseConsumer<Message<H
@Override
public void updateCapacity(final CapacityChannel capacityChannel) throws IOException {
final AsyncEntityConsumer<T> dataConsumer = dataConsumerRef.get();
- dataConsumer.updateCapacity(capacityChannel);
+ if (dataConsumer != null) {
+ dataConsumer.updateCapacity(capacityChannel);
+ } else {
+ capacityChannel.update(Integer.MAX_VALUE);
+ }
}
@Override
public void consume(final ByteBuffer src) throws IOException {
final AsyncEntityConsumer<T> dataConsumer = dataConsumerRef.get();
- dataConsumer.consume(src);
+ if (dataConsumer != null) {
+ dataConsumer.consume(src);
+ }
}
@Override
public void streamEnd(final List<? extends Header> trailers) throws HttpException, IOException {
final AsyncEntityConsumer<T> dataConsumer = dataConsumerRef.get();
- dataConsumer.streamEnd(trailers);
+ if (dataConsumer != null) {
+ dataConsumer.streamEnd(trailers);
+ }
}
@Override
=====================================
httpcore5/src/main/java/org/apache/hc/core5/pool/LaxConnPool.java
=====================================
@@ -466,8 +466,10 @@ public class LaxConnPool<T, C extends ModalCloseable> implements ManagedConnPool
try {
return super.get(timeout, unit);
} catch (final TimeoutException ex) {
- cancel();
- throw ex;
+ if (cancel()) {
+ throw ex;
+ }
+ return super.get();
}
}
=====================================
httpcore5/src/main/java/org/apache/hc/core5/pool/RouteSegmentedConnPool.java
=====================================
@@ -173,6 +173,19 @@ public final class RouteSegmentedConnPool<R, C extends ModalCloseable> implement
this.cancelled = false;
this.timeoutTask = null;
}
+
+ @Override
+ public PoolEntry<R, C> get(final long timeout, final TimeUnit unit)
+ throws InterruptedException, java.util.concurrent.ExecutionException, TimeoutException {
+ try {
+ return super.get(timeout, unit);
+ } catch (final TimeoutException ex) {
+ if (cancel(true)) {
+ throw ex;
+ }
+ return super.get();
+ }
+ }
}
@Override
=====================================
httpcore5/src/main/java/org/apache/hc/core5/pool/StrictConnPool.java
=====================================
@@ -177,8 +177,10 @@ public class StrictConnPool<T, C extends ModalCloseable> implements ManagedConnP
try {
return super.get(timeout, unit);
} catch (final TimeoutException ex) {
- cancel();
- throw ex;
+ if (cancel()) {
+ throw ex;
+ }
+ return super.get();
}
}
=====================================
httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
=====================================
@@ -93,7 +93,6 @@ public class SSLIOSession implements IOSession {
private final AtomicInteger outboundClosedCount;
private final AtomicReference<TLSHandShakeState> handshakeStateRef;
private final IOEventHandler internalEventHandler;
- private final int packetBufferSize;
private int appEventMask;
@@ -180,9 +179,9 @@ public class SSLIOSession implements IOSession {
final SSLSession sslSession = this.sslEngine.getSession();
// Allocate buffers for network (encrypted) data
- this.packetBufferSize = sslSession.getPacketBufferSize();
- this.inEncrypted = SSLManagedBuffer.create(sslBufferMode, packetBufferSize);
- this.outEncrypted = SSLManagedBuffer.create(sslBufferMode, packetBufferSize);
+ final int netBufferSize = sslSession.getPacketBufferSize();
+ this.inEncrypted = SSLManagedBuffer.create(sslBufferMode, netBufferSize);
+ this.outEncrypted = SSLManagedBuffer.create(sslBufferMode, netBufferSize);
// Allocate buffers for application (unencrypted) data
final int appBufferSize = sslSession.getApplicationBufferSize();
@@ -670,18 +669,9 @@ public class SSLIOSession implements IOSession {
if (this.handshakeStateRef.get() == TLSHandShakeState.READY) {
return 0;
}
-
- for (;;) {
- final ByteBuffer outEncryptedBuf = this.outEncrypted.acquire();
- final SSLEngineResult result = doWrap(src, outEncryptedBuf);
- if (result.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW) {
- // We don't release the buffer here, it will be expanded (if needed)
- // and returned by the next attempt of SSLManagedBuffer#acquire() call.
- this.outEncrypted.ensureWriteable(packetBufferSize);
- } else {
- return result.bytesConsumed();
- }
- }
+ final ByteBuffer outEncryptedBuf = this.outEncrypted.acquire();
+ final SSLEngineResult result = doWrap(src, outEncryptedBuf);
+ return result.bytesConsumed();
} finally {
this.session.getLock().unlock();
}
=====================================
httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLManagedBuffer.java
=====================================
@@ -57,54 +57,13 @@ abstract class SSLManagedBuffer {
*/
abstract boolean hasData();
- /**
- * Expands the underlying buffer's to make sure it has enough write capacity to accommodate
- * the required amount of bytes. This method has no side effect if the buffer has enough writeable
- * capacity left.
- * @param size the required write capacity
- */
- abstract void ensureWriteable(final int size);
-
- /**
- * Helper method to ensure additional writeable capacity with respect to the source buffer. It
- * allocates a new buffer and copies all the data if needed, returning the new buffer. This method
- * has no side effect if the source buffer has enough writeable capacity left.
- * @param src source buffer
- * @param size the required write capacity
- * @return new buffer (or the source buffer of it has enough writeable capacity left)
- */
- ByteBuffer ensureWriteable(final ByteBuffer src, final int size) {
- if (src == null) {
- // Nothing to do, the buffer is not allocated
- return null;
- }
-
- // There is not enough capacity left, we need to expand
- if (src.remaining() < size) {
- final int additionalCapacityNeeded = size - src.remaining();
- final ByteBuffer expanded = ByteBuffer.allocate(src.capacity() + additionalCapacityNeeded);
-
- // use a duplicated buffer so we don't disrupt the limit of the original buffer
- final ByteBuffer tmp = src.duplicate();
- tmp.flip();
-
- // Copy to expanded buffer
- expanded.put(tmp);
-
- // Use a new buffer
- return expanded;
- } else {
- return src;
- }
- }
-
static SSLManagedBuffer create(final SSLBufferMode mode, final int size) {
return mode == SSLBufferMode.DYNAMIC ? new DynamicBuffer(size) : new StaticBuffer(size);
}
static final class StaticBuffer extends SSLManagedBuffer {
- private ByteBuffer buffer;
+ private final ByteBuffer buffer;
public StaticBuffer(final int size) {
Args.positive(size, "size");
@@ -131,10 +90,6 @@ abstract class SSLManagedBuffer {
return buffer.position() > 0;
}
- @Override
- void ensureWriteable(final int size) {
- buffer = ensureWriteable(buffer, size);
- }
}
static final class DynamicBuffer extends SSLManagedBuffer {
@@ -171,10 +126,6 @@ abstract class SSLManagedBuffer {
return wrapped != null && wrapped.position() > 0;
}
- @Override
- void ensureWriteable(final int size) {
- wrapped = ensureWriteable(wrapped, size);
- }
}
}
=====================================
httpcore5/src/test/java/org/apache/hc/core5/pool/TestStrictConnPoolLeaseTimeoutRace.java
=====================================
@@ -0,0 +1,160 @@
+/*
+ * ====================================================================
+ * 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.core5.pool;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import org.apache.hc.core5.http.SocketModalCloseable;
+import org.apache.hc.core5.io.CloseMode;
+import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class TestConnPoolLeaseTimeout {
+
+ private static final Timeout TIMEOUT = Timeout.ofSeconds(30);
+
+ static final class DummyConn implements SocketModalCloseable {
+
+ private volatile Timeout socketTimeout;
+
+ @Override
+ public Timeout getSocketTimeout() {
+ return socketTimeout;
+ }
+
+ @Override
+ public void setSocketTimeout(final Timeout timeout) {
+ this.socketTimeout = timeout;
+ }
+
+ @Override
+ public void close(final CloseMode closeMode) {
+ }
+
+ @Override
+ public void close() throws IOException {
+ }
+ }
+
+ static final class PoolCase {
+ final String name;
+ final Supplier<ManagedConnPool<String, DummyConn>> supplier;
+
+ PoolCase(final String name, final Supplier<ManagedConnPool<String, DummyConn>> supplier) {
+ this.name = name;
+ this.supplier = supplier;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+
+ static Stream<PoolCase> pools() {
+ return Stream.of(
+ new PoolCase("STRICT", () -> new StrictConnPool<>(1, 1)),
+ new PoolCase("LAX", () -> new LaxConnPool<>(1)),
+ new PoolCase("OFFLOCK", () -> new RouteSegmentedConnPool<>(
+ 1,
+ 1,
+ TimeValue.NEG_ONE_MILLISECOND,
+ PoolReusePolicy.LIFO,
+ new DefaultDisposalCallback<>()))
+ );
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("pools")
+ @org.junit.jupiter.api.Timeout(60)
+ void testLeaseTimeoutDoesNotLeakLeasedEntries(final PoolCase poolCase) throws Exception {
+ final ManagedConnPool<String, DummyConn> pool = poolCase.supplier.get();
+
+ final String route = "route-1";
+ final Timeout requestTimeout = Timeout.ofMicroseconds(1);
+
+ final int concurrentThreads = 10;
+ final CountDownLatch countDownLatch = new CountDownLatch(concurrentThreads);
+ final AtomicLong n = new AtomicLong(concurrentThreads * 100);
+
+ final ExecutorService executorService = Executors.newFixedThreadPool(concurrentThreads);
+ final AtomicReference<Exception> unexpectedException = new AtomicReference<>();
+ try {
+ for (int i = 0; i < concurrentThreads; i++) {
+ executorService.execute(() -> {
+ try {
+ while (n.decrementAndGet() > 0) {
+ final Future<PoolEntry<String, DummyConn>> f = pool.lease(route, null, requestTimeout, null);
+ try {
+ final PoolEntry<String, DummyConn> entry =
+ f.get(requestTimeout.getDuration(), requestTimeout.getTimeUnit());
+ pool.release(entry, true);
+ } catch (final InterruptedException ex) {
+ Thread.currentThread().interrupt();
+ unexpectedException.compareAndSet(null, ex);
+ } catch (final TimeoutException ex) {
+ f.cancel(true);
+ } catch (final ExecutionException ex) {
+ f.cancel(true);
+ if (!(ex.getCause() instanceof TimeoutException)) {
+ unexpectedException.compareAndSet(null, ex);
+ }
+ }
+ }
+ } finally {
+ countDownLatch.countDown();
+ }
+ });
+ }
+
+ Assertions.assertTrue(countDownLatch.await(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit()));
+ Assertions.assertTrue(n.get() <= 0);
+ Assertions.assertNull(unexpectedException.get());
+
+ final PoolStats stats = pool.getStats(route);
+ Assertions.assertEquals(0, stats.getLeased());
+
+ } finally {
+ executorService.shutdownNow();
+ executorService.awaitTermination(TIMEOUT.getDuration(), TIMEOUT.getTimeUnit());
+ pool.close(CloseMode.GRACEFUL);
+ }
+ }
+}
\ No newline at end of file
=====================================
pom.xml
=====================================
@@ -33,7 +33,7 @@
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5-parent</artifactId>
<name>Apache HttpComponents Core</name>
- <version>5.4.2</version>
+ <version>5.4.3</version>
<description>Apache HttpComponents Core is a library of components for building HTTP enabled services</description>
<url>https://hc.apache.org/httpcomponents-core-5.4.x/${project.version}/</url>
<inceptionYear>2005</inceptionYear>
@@ -48,7 +48,7 @@
<connection>scm:git:https://gitbox.apache.org/repos/asf/httpcomponents-core.git</connection>
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/httpcomponents-core.git</developerConnection>
<url>https://github.com/apache/httpcomponents-core/tree/${project.scm.tag}</url>
- <tag>5.4.2</tag>
+ <tag>5.4.3</tag>
</scm>
<distributionManagement>
View it on GitLab: https://salsa.debian.org/java-team/httpcomponents-core5/-/compare/d1dee5588f30d50199ede9e8a692786eca0b6a78...cdf7241e45720fe8350115c5b8f28f79c9a972ab
--
View it on GitLab: https://salsa.debian.org/java-team/httpcomponents-core5/-/compare/d1dee5588f30d50199ede9e8a692786eca0b6a78...cdf7241e45720fe8350115c5b8f28f79c9a972ab
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20260808/01ece189/attachment.htm>
More information about the pkg-java-commits
mailing list