From d191de891a4d2be48908c6964e5cb157d002dae6 Mon Sep 17 00:00:00 2001 From: Joshua Rogers Date: Wed, 20 May 2026 00:37:27 +0200 Subject: [PATCH] telnet: honor CURLOPT_TIMEOUT in send_telnet_data() The poll-before-write loop used -1 (infinite) as the Curl_poll timeout, so a peer that stops reading could stall the transfer indefinitely, bypassing CURLOPT_TIMEOUT. Use Curl_timeleft_ms() instead and return CURLE_OPERATION_TIMEDOUT when the deadline is reached or exceeded. Closes #21685 --- lib/telnet.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/telnet.c b/lib/telnet.c index d1faec87a8..83114ef2aa 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -53,6 +53,7 @@ #include "curl_trc.h" #include "progress.h" #include "arpa_telnet.h" +#include "connect.h" #include "select.h" #include "curlx/strparse.h" @@ -645,13 +646,19 @@ static CURLcode send_telnet_data(struct Curl_easy *data, while(!result && total_written < outlen) { /* Make sure socket is writable to avoid EWOULDBLOCK condition */ struct pollfd pfd[1]; + timediff_t timeout_ms = Curl_timeleft_ms(data); pfd[0].fd = conn->sock[FIRSTSOCKET]; pfd[0].events = POLLOUT; - switch(Curl_poll(pfd, 1, -1)) { + if(timeout_ms < 0) + return CURLE_OPERATION_TIMEDOUT; + /* 0 means no timeout configured; pass -1 to poll for infinite wait */ + switch(Curl_poll(pfd, 1, timeout_ms ? timeout_ms : -1)) { case -1: /* error, abort writing */ - case 0: /* timeout (will never happen) */ result = CURLE_SEND_ERROR; break; + case 0: /* timeout */ + result = CURLE_OPERATION_TIMEDOUT; + break; default: /* write! */ bytes_written = 0; result = Curl_xfer_send(data, outbuf + total_written,