This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new 2232a8d8f4 Review "Cap the NIO sender SO_TIMEOUT at Integer.MAX_VALUE"
2232a8d8f4 is described below
commit 2232a8d8f49f7aee5662b58ac47f572fe92db22b
Author: Mark Thomas <[email protected]>
AuthorDate: Fri Oct 23 18:01:58 2026 +0100
Review "Cap the NIO sender SO_TIMEOUT at Integer.MAX_VALUE"
Add additional caps
Co-authored by: Claude / Sonnet 5.5
---
.../group/interceptors/TcpFailureDetector.java | 6 ++-
.../TestTcpFailureDetectorLivenessChecks.java | 19 ++++++++
.../tribes/transport/nio/TestNioSender.java | 54 ++++++++++++++++++++++
3 files changed, 77 insertions(+), 2 deletions(-)
diff --git
a/java/org/apache/catalina/tribes/group/interceptors/TcpFailureDetector.java
b/java/org/apache/catalina/tribes/group/interceptors/TcpFailureDetector.java
index ee10f0962e..b970b1149e 100644
--- a/java/org/apache/catalina/tribes/group/interceptors/TcpFailureDetector.java
+++ b/java/org/apache/catalina/tribes/group/interceptors/TcpFailureDetector.java
@@ -703,8 +703,10 @@ public class TcpFailureDetector extends
ChannelInterceptorBase implements TcpFai
try (Socket socket = new Socket()) {
InetAddress ia = InetAddress.getByAddress(mbr.getHost());
InetSocketAddress addr = new InetSocketAddress(ia, port);
- socket.setSoTimeout((int) readTimeout);
- socket.connect(addr, (int) conTimeout);
+ // The timeouts are longs but the socket takes ints. Cap them
rather than let a large value overflow to a
+ // negative one, which the socket rejects.
+ socket.setSoTimeout((int) Math.min(readTimeout,
Integer.MAX_VALUE));
+ socket.connect(addr, (int) Math.min(conTimeout,
Integer.MAX_VALUE));
if (sendTest) {
ChannelData data = new ChannelData(true);
data.setAddress(getLocalMember(false));
diff --git
a/test/org/apache/catalina/tribes/group/interceptors/TestTcpFailureDetectorLivenessChecks.java
b/test/org/apache/catalina/tribes/group/interceptors/TestTcpFailureDetectorLivenessChecks.java
index e09322367d..a18323a8da 100644
---
a/test/org/apache/catalina/tribes/group/interceptors/TestTcpFailureDetectorLivenessChecks.java
+++
b/test/org/apache/catalina/tribes/group/interceptors/TestTcpFailureDetectorLivenessChecks.java
@@ -16,6 +16,8 @@
*/
package org.apache.catalina.tribes.group.interceptors;
+import java.net.InetAddress;
+import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -30,6 +32,7 @@ import org.junit.Test;
import org.apache.catalina.tribes.Member;
import org.apache.catalina.tribes.group.ChannelInterceptorBase;
import org.apache.catalina.tribes.group.GroupChannel;
+import org.apache.catalina.tribes.membership.MemberImpl;
import org.apache.catalina.tribes.membership.StaticMember;
/**
@@ -570,4 +573,20 @@ public class TestTcpFailureDetectorLivenessChecks {
Assert.assertNull("A forgotten member must not be added by a running
check", detector.getMember(member));
Assert.assertTrue(recorder.added.isEmpty());
}
+
+ /*
+ * Timeouts too large for the int socket timeouts must be capped rather
than overflow to a negative value that
+ * the socket rejects, which would make a live member look dead.
+ */
+ @Test
+ public void testMemberAliveWithTimeoutsAboveIntegerMax() throws Exception {
+ try (ServerSocket server = new ServerSocket(0, 1,
InetAddress.getLoopbackAddress())) {
+ TcpFailureDetector detector = new TcpFailureDetector();
+ detector.setChannel(new GroupChannel());
+ MemberImpl member = new MemberImpl("127.0.0.1",
server.getLocalPort(), 0);
+
+ Assert.assertTrue(detector.memberAlive(member, new byte[0], false,
false,
+ Long.MAX_VALUE, Long.MAX_VALUE, 0));
+ }
+ }
}
diff --git a/test/org/apache/catalina/tribes/transport/nio/TestNioSender.java
b/test/org/apache/catalina/tribes/transport/nio/TestNioSender.java
new file mode 100644
index 0000000000..cd72249876
--- /dev/null
+++ b/test/org/apache/catalina/tribes/transport/nio/TestNioSender.java
@@ -0,0 +1,54 @@
+/*
+ * 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.catalina.tribes.transport.nio;
+
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.nio.channels.Selector;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.catalina.tribes.membership.MemberImpl;
+
+public class TestNioSender {
+
+ /*
+ * A timeout too large for the int SO_TIMEOUT must be capped rather than
overflow to a negative value that the
+ * socket rejects.
+ */
+ @Test
+ public void testConnectWithTimeoutAboveIntegerMax() throws Exception {
+ try (DatagramSocket target = new DatagramSocket(0,
InetAddress.getLoopbackAddress());
+ Selector selector = Selector.open()) {
+ MemberImpl member = new MemberImpl("127.0.0.1", 4000, 0);
+ member.setUdpPort(target.getLocalPort());
+
+ NioSender sender = new NioSender();
+ sender.setDestination(member);
+ sender.setUdpBased(true);
+ sender.setSelector(selector);
+ sender.setTimeout(Long.MAX_VALUE);
+ try {
+ sender.connect();
+ Assert.assertTrue(sender.isConnected());
+ } finally {
+ sender.disconnect();
+ }
+ }
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]