This is an automated email from the ASF dual-hosted git repository.
oscerd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 3491e1b7a9ac CAMEL-24936: camel-netty - NettyConverter.toByteArray
copies only the readable bytes of the ByteBuf (#26781)
3491e1b7a9ac is described below
commit 3491e1b7a9ac70663d83201b4ca47d5ff338109b
Author: Andrea Cosentino <[email protected]>
AuthorDate: Fri Sep 25 10:57:42 2026 +0200
CAMEL-24936: camel-netty - NettyConverter.toByteArray copies only the
readable bytes of the ByteBuf (#26781)
buffer.array() returned the whole backing array, ignoring
arrayOffset()/readerIndex()/readableBytes();
for a shared or pooled backing array that can include bytes outside this
buffer's own slice, and it also
handed back a reference to a buffer that may later be reused. Always copy
exactly the readable region
instead, consistent with the non-array branch, regardless of the underlying
allocator.
Signed-off-by: Andrea Cosentino <[email protected]>
Co-authored-by: Claude Opus 4.8 <[email protected]>
---
.../camel/component/netty/NettyConverter.java | 19 +++++--------
.../camel/component/netty/NettyConverterTest.java | 31 ++++++++++++++++++++++
.../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc | 14 ++++++++++
3 files changed, 52 insertions(+), 12 deletions(-)
diff --git
a/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyConverter.java
b/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyConverter.java
index 36920d1034df..98a4c2ffd3bc 100644
---
a/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyConverter.java
+++
b/components/camel-netty/src/main/java/org/apache/camel/component/netty/NettyConverter.java
@@ -32,6 +32,7 @@ import org.w3c.dom.Document;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufInputStream;
+import io.netty.buffer.ByteBufUtil;
import org.apache.camel.Converter;
import org.apache.camel.Exchange;
import org.apache.camel.support.DeserializationFilterHelper;
@@ -48,18 +49,12 @@ public final class NettyConverter {
@Converter
public static byte[] toByteArray(ByteBuf buffer, Exchange exchange) {
- if (buffer.hasArray()) {
- return buffer.array();
- }
- byte[] bytes = new byte[buffer.readableBytes()];
- int readerIndex = buffer.readerIndex();
- buffer.retain();
- try {
- buffer.getBytes(readerIndex, bytes);
- } finally {
- buffer.release();
- }
- return bytes;
+ // Copy only the readable region of the buffer. Returning
buffer.array() directly would hand back the
+ // whole backing array, ignoring
arrayOffset()/readerIndex()/readableBytes(): for a shared or pooled
+ // backing array that can include bytes outside this buffer's own
slice, and it also exposes a reference
+ // to a buffer that may later be reused. ByteBufUtil.getBytes() copies
exactly the readable bytes for
+ // every buffer kind (heap or direct, pooled or unpooled).
+ return ByteBufUtil.getBytes(buffer);
}
@Converter
diff --git
a/components/camel-netty/src/test/java/org/apache/camel/component/netty/NettyConverterTest.java
b/components/camel-netty/src/test/java/org/apache/camel/component/netty/NettyConverterTest.java
index b68f146efd75..bff50bb17686 100644
---
a/components/camel-netty/src/test/java/org/apache/camel/component/netty/NettyConverterTest.java
+++
b/components/camel-netty/src/test/java/org/apache/camel/component/netty/NettyConverterTest.java
@@ -16,8 +16,11 @@
*/
package org.apache.camel.component.netty;
+import java.nio.charset.StandardCharsets;
+
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
+import io.netty.buffer.Unpooled;
import org.apache.camel.support.DefaultExchange;
import org.apache.camel.test.junit6.CamelTestSupport;
import org.junit.jupiter.api.BeforeEach;
@@ -25,6 +28,7 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Utility test to verify netty type converter.
@@ -64,4 +68,31 @@ public class NettyConverterTest extends CamelTestSupport {
assertEquals(PAYLOAD, result);
}
+ /**
+ * A heap (array-backed) buffer whose backing array is larger than the
readable region, and whose reader index has
+ * been advanced past a prefix, must convert to exactly the readable bytes
- not the whole backing array. Converting
+ * via buffer.array() used to return the full backing array (prefix +
payload + spare capacity).
+ */
+ @Test
+ public void testConversionHeapBufferReturnsOnlyReadableBytes() {
+ byte[] payload = PAYLOAD.getBytes(StandardCharsets.UTF_8);
+ byte[] prefix = "SKIP".getBytes(StandardCharsets.UTF_8);
+ // Heap buffer with spare capacity so its backing array is larger than
the readable region
+ ByteBuf heap = Unpooled.buffer(prefix.length + payload.length + 32);
+ try {
+ heap.writeBytes(prefix);
+ heap.writeBytes(payload);
+ // Skip the prefix: only "payload" is readable now
+ heap.readerIndex(prefix.length);
+
+ assertTrue(heap.hasArray(), "expected an array-backed heap buffer
for this test");
+
+ byte[] result = NettyConverter.toByteArray(heap, null);
+ assertEquals(payload.length, result.length);
+ assertEquals(PAYLOAD, new String(result, StandardCharsets.UTF_8));
+ } finally {
+ heap.release();
+ }
+ }
+
}
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
index 3bcd2615c9e2..6b12d19acaab 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
@@ -945,6 +945,20 @@ The same default is now also applied to the `ClientConfig`
that Camel builds for
endpoints, when neither a referenced `ClientConfig` nor `hazelcastConfigUri`
is supplied. Client mode
previously behaved differently from node mode for an otherwise identical
endpoint configuration.
+=== camel-netty - NettyConverter.toByteArray returns a copy of the buffer's
readable bytes
+
+The `ByteBuf` to `byte[]` type converter (`NettyConverter.toByteArray`, also
used when converting a Netty
+HTTP response body and by `camel-hl7`, `camel-lumberjack` and `camel-syslog`)
now always returns a copy of
+exactly the buffer's readable region (`readerIndex()`..`readableBytes()`).
+
+Previously, for an array-backed (heap) buffer it returned the buffer's whole
backing array directly. That
+could include bytes outside the readable region and, for a pooled buffer,
bytes belonging to other
+allocations; the returned array was also a live reference into a buffer that
could later be recycled.
+
+If your code relied on mutating the returned `byte[]` to write through to the
original `ByteBuf`, that no
+longer has any effect. The converter now behaves consistently for heap and
direct, pooled and unpooled
+buffers.
+
=== camel-http, camel-http-common, camel-netty-http, camel-undertow,
camel-vertx-http - property placeholders in HTTP URI override headers
The HTTP producers no longer resolve property placeholders (`{{...}}`) in the
message-supplied