From 2b1a9afbfbb5491665bfbdd560486a310ca49755 Mon Sep 17 00:00:00 2001 From: Misaki Shioi <31817032+shioimm@users.noreply.github.com> Date: Tue, 16 Dec 2025 19:52:45 +0900 Subject: Fix: Do not pass negative timeout to Addrinfo#connect_internal (#15578) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change fixes a bug where, with `Socket.tcp`’s `fast_fallback option` disabled, specifying `open_timeout` could unintentionally pass a negative value to `Addrinfo#connect_internal`, `causing an ArgumentError`. ``` ❯ ruby -rsocket -e 'p Socket.tcp("localhost", 9292, open_timeout: 1, fast_fallback: false)' /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:64:in 'IO#wait_writable': time interval must not be negative (ArgumentError) sock.wait_writable(timeout) or ^^^^^^^ from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:64:in 'Addrinfo#connect_internal' from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:141:in 'Addrinfo#connect' from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:964:in 'block in Socket.tcp_without_fast_fallback' from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:231:in 'Array#each' from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:231:in 'Addrinfo.foreach' from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:945:in 'Socket.tcp_without_fast_fallback' from /Users/misaki-shioi/src/install/lib/ruby/4.0.0+0/socket.rb:671:in 'Socket.tcp' from -e:1:in '
' ``` --- ext/socket/lib/socket.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'ext/socket') diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb index 9862c92c0b..f47b5bc1d1 100644 --- a/ext/socket/lib/socket.rb +++ b/ext/socket/lib/socket.rb @@ -948,7 +948,14 @@ class Socket < BasicSocket local_addr = nil end begin - timeout = open_timeout ? open_timeout - (current_clock_time - starts_at) : connect_timeout + timeout = + if open_timeout + t = open_timeout - (current_clock_time - starts_at) + t.negative? ? 0 : t + else + connect_timeout + end + sock = local_addr ? ai.connect_from(local_addr, timeout:) : ai.connect(timeout:) -- cgit v1.2.3