From d881b911336eed4a939631f56e5ebe05b7954481 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 8 Jan 2026 23:57:58 +0100 Subject: [PATCH] urldata: convert 'long' fields to fixed variable types Makes sure they work identically cross-platform, as long varies in size between Windows vs non-Windows. Makes Curl_easy 16 bytes smaller on 64 bit Linux. This reduces support for the RTSP cseq counters to 32 bit (down from 63 bit previously on 64 bit non-Windows), but it is probably safe. Implementations probably rarely support anything above 32 bits anyway and this is how curl has worked on Windows since always. There is now only one 'long' left in urldata.h (in the ssl_config_data struct). That field, certverifyresult, is used to store the response code from TLS backend code and in the OpenSSL case that function returns an actual 'long'. Closes #20227 --- lib/getinfo.c | 7 ++++++- lib/progress.c | 8 +++----- lib/rtsp.c | 25 ++++++++++++------------- lib/setopt.c | 21 +++++++++++++-------- lib/urldata.h | 16 ++++++++-------- 5 files changed, 42 insertions(+), 35 deletions(-) diff --git a/lib/getinfo.c b/lib/getinfo.c index e094ffd134..a59c2d3eb2 100644 --- a/lib/getinfo.c +++ b/lib/getinfo.c @@ -281,7 +281,12 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, *param_longp = data->state.os_errno; break; case CURLINFO_NUM_CONNECTS: - *param_longp = data->info.numconnects; +#if SIZEOF_LONG < SIZEOF_CURL_OFF_T + if(data->info.numconnects > LONG_MAX) + *param_longp = LONG_MAX; + else +#endif + *param_longp = (long)data->info.numconnects; break; case CURLINFO_LASTSOCKET: sockfd = Curl_getconnectinfo(data, NULL); diff --git a/lib/progress.c b/lib/progress.c index 9cbd2674f9..433c2b3498 100644 --- a/lib/progress.c +++ b/lib/progress.c @@ -152,11 +152,9 @@ UNITTEST CURLcode pgrs_speedcheck(struct Curl_easy *data, if(howlong >= data->set.low_speed_time * 1000) { /* too long */ - failf(data, - "Operation too slow. " - "Less than %ld bytes/sec transferred the last %ld seconds", - data->set.low_speed_limit, - data->set.low_speed_time); + failf(data, "Operation too slow. Less than %" FMT_OFF_T + " bytes/sec transferred the last %u seconds", + data->set.low_speed_limit, data->set.low_speed_time); return CURLE_OPERATION_TIMEDOUT; } } diff --git a/lib/rtsp.c b/lib/rtsp.c index 93bcbeb4e8..f2bf647166 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -66,8 +66,8 @@ struct rtsp_conn { /* RTSP transfer data */ struct RTSP { - long CSeq_sent; /* CSeq of this request */ - long CSeq_recv; /* CSeq received */ + uint32_t CSeq_sent; /* CSeq of this request */ + uint32_t CSeq_recv; /* CSeq received */ }; #define RTP_PKT_LENGTH(p) ((((unsigned int)((unsigned char)((p)[2]))) << 8) | \ @@ -245,16 +245,16 @@ static CURLcode rtsp_done(struct Curl_easy *data, if(!status && !httpStatus) { /* Check the sequence numbers */ - long CSeq_sent = rtsp->CSeq_sent; - long CSeq_recv = rtsp->CSeq_recv; + uint32_t CSeq_sent = rtsp->CSeq_sent; + uint32_t CSeq_recv = rtsp->CSeq_recv; if((data->set.rtspreq != RTSPREQ_RECEIVE) && (CSeq_sent != CSeq_recv)) { failf(data, - "The CSeq of this request %ld did not match the response %ld", + "The CSeq of this request %u did not match the response %u", CSeq_sent, CSeq_recv); return CURLE_RTSP_CSEQ_ERROR; } if(data->set.rtspreq == RTSPREQ_RECEIVE && (rtspc->rtp_channel == -1)) { - infof(data, "Got an RTP Receive with a CSeq of %ld", CSeq_recv); + infof(data, "Got an RTP Receive with a CSeq of %u", CSeq_recv); } if(data->set.rtspreq == RTSPREQ_RECEIVE && data->req.eos_written) { @@ -346,11 +346,11 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) { struct connectdata *conn = data->conn; CURLcode result = CURLE_OK; - Curl_RtspReq rtspreq = data->set.rtspreq; + const Curl_RtspReq rtspreq = data->set.rtspreq; struct RTSP *rtsp = Curl_meta_get(data, CURL_META_RTSP_EASY); struct dynbuf req_buffer; - unsigned char httpversion = 11; /* RTSP is close to HTTP/1.1, sort of... */ - + const unsigned char httpversion = 11; /* RTSP is close to HTTP/1.1, sort + of... */ const char *p_request = NULL; const char *p_session_id = NULL; const char *p_accept = NULL; @@ -573,7 +573,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) result = curlx_dyn_addf(&req_buffer, "%s %s RTSP/1.0\r\n" /* Request Stream-URI RTSP/1.0 */ - "CSeq: %ld\r\n", /* CSeq */ + "CSeq: %u\r\n", /* CSeq */ p_request, p_stream_uri, rtsp->CSeq_sent); if(result) goto out; @@ -995,12 +995,11 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header) if(!rtsp) return CURLE_FAILED_INIT; curlx_str_passblanks(&p); - if(curlx_str_number(&p, &CSeq, LONG_MAX)) { + if(curlx_str_number(&p, &CSeq, UINT_MAX)) { failf(data, "Unable to read the CSeq header: [%s]", header); return CURLE_RTSP_CSEQ_ERROR; } - rtsp->CSeq_recv = (long)CSeq; /* mark the request */ - data->state.rtsp_CSeq_recv = (long)CSeq; /* update the handle */ + data->state.rtsp_CSeq_recv = rtsp->CSeq_recv = (uint32_t)CSeq; } else if(checkprefix("Session:", header)) { const char *start, *end; diff --git a/lib/setopt.c b/lib/setopt.c index 4b66cf3345..402a1f6d9a 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -1050,9 +1050,10 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, s->low_speed_limit = arg; break; case CURLOPT_LOW_SPEED_TIME: - if(arg < 0) - return CURLE_BAD_FUNCTION_ARGUMENT; - s->low_speed_time = arg; + result = value_range(&arg, 0, 0, USHRT_MAX); + if(result) + return result; + s->low_speed_time = (uint16_t)arg; break; case CURLOPT_PORT: if((arg < 0) || (arg > 65535)) @@ -1190,11 +1191,17 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, case CURLOPT_RTSP_REQUEST: return setopt_RTSP_REQUEST(data, arg); case CURLOPT_RTSP_CLIENT_CSEQ: - data->state.rtsp_next_client_CSeq = arg; + result = value_range(&arg, 0, 0, INT_MAX); + if(result) + return result; + data->state.rtsp_next_client_CSeq = (uint32_t)arg; break; case CURLOPT_RTSP_SERVER_CSEQ: - data->state.rtsp_next_server_CSeq = arg; + result = value_range(&arg, 0, 0, INT_MAX); + if(result) + return result; + data->state.rtsp_next_server_CSeq = (uint32_t)arg; break; #endif /* !CURL_DISABLE_RTSP */ @@ -1231,9 +1238,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, return setopt_set_timeout_ms(&s->happy_eyeballs_timeout, arg); case CURLOPT_UPKEEP_INTERVAL_MS: - if(arg < 0) - return CURLE_BAD_FUNCTION_ARGUMENT; - s->upkeep_interval_ms = arg; + return setopt_set_timeout_ms(&s->upkeep_interval_ms, arg); break; case CURLOPT_MAXAGE_CONN: return setopt_set_timeout_sec(&s->conn_max_idle_ms, arg); diff --git a/lib/urldata.h b/lib/urldata.h index bc932d2e40..84bfaeb102 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -753,11 +753,11 @@ struct PureInfo { time_t filetime; /* If requested, this is might get set. Set to -1 if the time was unretrievable. */ curl_off_t request_size; /* the amount of bytes sent in the request(s) */ + curl_off_t numconnects; /* how many new connections libcurl created */ uint32_t proxyauthavail; /* what proxy auth types were announced */ uint32_t httpauthavail; /* what host auth types were announced */ uint32_t proxyauthpicked; /* selected proxy auth type */ uint32_t httpauthpicked; /* selected host auth type */ - long numconnects; /* how many new connection did libcurl created */ char *contenttype; /* the content type of the object */ char *wouldredirect; /* URL this would have been redirected to if asked to */ curl_off_t retry_after; /* info from Retry-After: header */ @@ -998,10 +998,9 @@ struct UrlState { #ifndef CURL_DISABLE_RTSP /* This RTSP state information survives requests and connections */ - long rtsp_next_client_CSeq; /* the session's next client CSeq */ - long rtsp_next_server_CSeq; /* the session's next server CSeq */ - long rtsp_CSeq_recv; /* most recent CSeq received */ - + uint32_t rtsp_next_client_CSeq; /* the session's next client CSeq */ + uint32_t rtsp_next_server_CSeq; /* the session's next server CSeq */ + uint32_t rtsp_CSeq_recv; /* most recent CSeq received */ uint8_t rtp_channel_mask[32]; /* for the correctness checking of the interleaved data */ #endif @@ -1334,8 +1333,7 @@ struct UserDefined { timediff_t conn_max_age_ms; /* max time since creation to allow a connection that is to be reused */ curl_off_t filesize; /* size of file to upload, -1 means unknown */ - long low_speed_limit; /* bytes/second */ - long low_speed_time; /* number of seconds */ + curl_off_t low_speed_limit; /* bytes/second */ curl_off_t max_send_speed; /* high speed limit in bytes/second for upload */ curl_off_t max_recv_speed; /* high speed limit in bytes/second for download */ @@ -1433,7 +1431,8 @@ struct UserDefined { curl_resolver_start_callback resolver_start; /* optional callback called before resolver start */ void *resolver_start_client; /* pointer to pass to resolver start callback */ - long upkeep_interval_ms; /* Time between calls for connection upkeep. */ + timediff_t upkeep_interval_ms; /* Time between calls for connection + upkeep. */ CURLU *uh; /* URL handle for the current parsed URL */ #ifndef CURL_DISABLE_HTTP void *trailer_data; /* pointer to pass to trailer data callback */ @@ -1450,6 +1449,7 @@ struct UserDefined { set to -1 for infinity */ uint16_t expect_100_timeout; /* in milliseconds */ uint16_t use_port; /* which port to use (when not using default) */ + uint16_t low_speed_time; /* number of seconds */ #ifndef CURL_DISABLE_BINDLOCAL uint16_t localport; /* local port number to bind to */ uint16_t localportrange; /* number of additional port numbers to test