This is an automated email from the ASF dual-hosted git repository.

markt-asf pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/9.0.x by this push:
     new e841d5600a Review "Cap the NIO sender SO_TIMEOUT at Integer.MAX_VALUE"
e841d5600a is described below

commit e841d5600aa290820fe5b4bc83f16d81a6b6e0ba
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 f0c0b9f1e4..308902dfcc 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]

Reply via email to