This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 11.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 8dc26c11c2718406713e65ad59329f0d18d948f6 Author: opencode <[email protected]> AuthorDate: Fri Oct 9 16:09:00 2026 +0200 Detach the unique id when shallow cloning a channel message The shallow clone shared the unique id byte array with the original message. TwoPhaseCommitInterceptor builds its confirmation message with this clone when deepclone is disabled and then generates a new id into the confirmation's id array in place, which overwrote the id of the caller's message. The wire data was already serialized at that point, but the in-memory id returned to the application by Channel.send afterwards identified the confirmation rather than the message that was sent. The clone now copies the id array, so a derived message can be given its own id without affecting the original. Fragment members still share the id of their original message by value, which is all the interceptors and the receiver side keying ever relied on. --- .../org/apache/catalina/tribes/io/ChannelData.java | 7 +++++- .../TestTwoPhaseCommitInterceptor.java | 25 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/java/org/apache/catalina/tribes/io/ChannelData.java b/java/org/apache/catalina/tribes/io/ChannelData.java index aad66da3db..0f798c8d85 100644 --- a/java/org/apache/catalina/tribes/io/ChannelData.java +++ b/java/org/apache/catalina/tribes/io/ChannelData.java @@ -310,7 +310,9 @@ public class ChannelData implements ChannelMessage { } /** - * Create a shallow clone, only the data gets recreated + * Create a shallow clone, the message data and the unique id are recreated so that the + * clone, for example a confirmation message derived from the original, can be given a new + * id without modifying the original message in place. * * @return ChannelData clone */ @@ -323,6 +325,9 @@ public class ChannelData implements ChannelMessage { // Cannot happen throw new AssertionError(); } + if (this.uniqueId != null) { + clone.uniqueId = this.uniqueId.clone(); + } if (this.message != null) { clone.message = new XByteBuffer(this.message.getBytesDirect(), false); clone.message.setLength(this.message.getLength()); diff --git a/test/org/apache/catalina/tribes/group/interceptors/TestTwoPhaseCommitInterceptor.java b/test/org/apache/catalina/tribes/group/interceptors/TestTwoPhaseCommitInterceptor.java index 7f33f2ce2d..b5ecc22a29 100644 --- a/test/org/apache/catalina/tribes/group/interceptors/TestTwoPhaseCommitInterceptor.java +++ b/test/org/apache/catalina/tribes/group/interceptors/TestTwoPhaseCommitInterceptor.java @@ -121,6 +121,31 @@ public class TestTwoPhaseCommitInterceptor { Assert.assertNull(chain.payloads.get(1)); } + @Test + public void testShallowCloneKeepsOriginalUniqueIdIntact() throws Exception { + TwoPhaseCommitInterceptor interceptor = new TwoPhaseCommitInterceptor(); + interceptor.setDeepclone(false); + RecordingSendChain chain = new RecordingSendChain(); + GroupChannel channel = new GroupChannel(); + interceptor.setChannel(channel); + interceptor.setNext(chain); + + MemberImpl member = new MemberImpl("localhost", 4000, -1); + ChannelData msg = createMessage(member); + byte[] originalId = msg.getUniqueId(); + byte[] savedId = originalId.clone(); + + interceptor.sendMessage(new Member[] { member }, msg, null); + + Assert.assertEquals(2, chain.messages.size()); + Assert.assertArrayEquals("Building the confirmation must not modify the original id in place", + savedId, msg.getUniqueId()); + Assert.assertNotSame("The clone must not share the id array with the original", + originalId, chain.messages.get(1).getUniqueId()); + Assert.assertFalse("The confirmation must carry a different id", + Arrays.equals(savedId, chain.messages.get(1).getUniqueId())); + } + @Test public void testOriginalSendFailureSkipsConfirmation() throws Exception { TwoPhaseCommitInterceptor interceptor = new TwoPhaseCommitInterceptor(); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
