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
This commit is contained in:
Joshua Rogers 2026-05-20 00:37:27 +02:00 committed by Daniel Stenberg
parent 9d19b47302
commit d191de891a
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2

View file

@ -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,