From cb2bcb681fc9044d2a7adaaa6210b61e2f7cff59 Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Wed, 12 Nov 2025 15:58:49 +0100 Subject: [PATCH] lib: eliminate size_t casts Add new functions in `curlx/warnless.h` for controlled type conversions: * curlx_uitouz, convert unsigned into to size_t (should always work) * curlx_uztoso, convert size_t to curl_off_t, capping at CURL_OFF_T_MAX * curlx_sztouz, convert ssize_t to size_t, return TRUE when ok * curlx_sotouz_range, convert curl_off_t to size_t interval, capping values to interval bounds Remove some unnecesary casts, convert some internal recv functions to the "return result, have size_t* arg" pattern. Closes #19495 --- lib/cf-h1-proxy.c | 2 +- lib/cf-h2-proxy.c | 2 +- lib/curlx/warnless.c | 35 +++++++++++++++ lib/curlx/warnless.h | 12 ++++++ lib/dict.c | 4 +- lib/http.c | 8 ++-- lib/http2.c | 96 +++++++++++++++++++++-------------------- lib/multi.c | 13 +++--- lib/sendf.c | 25 ++--------- lib/setopt.c | 12 +++--- lib/transfer.c | 58 +++++++++++-------------- lib/vquic/curl_ngtcp2.c | 23 +++------- lib/ws.c | 36 ++++++++-------- 13 files changed, 170 insertions(+), 156 deletions(-) diff --git a/lib/cf-h1-proxy.c b/lib/cf-h1-proxy.c index be01891bf0..ac0dc596f2 100644 --- a/lib/cf-h1-proxy.c +++ b/lib/cf-h1-proxy.c @@ -268,7 +268,7 @@ static CURLcode send_CONNECT(struct Curl_cfilter *cf, DEBUGASSERT(blen >= nwritten); ts->nsent += nwritten; - Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)nwritten); + Curl_debug(data, CURLINFO_HEADER_OUT, buf, nwritten); out: if(result) diff --git a/lib/cf-h2-proxy.c b/lib/cf-h2-proxy.c index 148caca71b..d38bd46952 100644 --- a/lib/cf-h2-proxy.c +++ b/lib/cf-h2-proxy.c @@ -847,7 +847,7 @@ static int tunnel_recv_callback(nghttp2_session *session, uint8_t flags, #endif } /* tunnel.recbuf has soft limit, any success MUST add all data */ - DEBUGASSERT((size_t)nwritten == len); + DEBUGASSERT(nwritten == len); return 0; } diff --git a/lib/curlx/warnless.c b/lib/curlx/warnless.c index bb636a9327..a0aa5eda13 100644 --- a/lib/curlx/warnless.c +++ b/lib/curlx/warnless.c @@ -290,3 +290,38 @@ size_t curlx_sitouz(int sinum) # pragma warning(pop) #endif } + +size_t curlx_uitouz(unsigned int uinum) +{ + return (size_t)uinum; +} + +size_t curlx_sotouz_range(curl_off_t sonum, size_t uzmin, size_t uzmax) +{ + if(sonum < 0) + return uzmin; +#if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T + if(sonum > SIZE_MAX) + return uzmax; +#endif + return CURLMIN(CURLMAX((size_t)sonum, uzmin), uzmax); +} + +bool curlx_sztouz(ssize_t sznum, size_t *puznum) +{ + if(sznum < 0) { + *puznum = 0; + return FALSE; + } + *puznum = (size_t)sznum; + return TRUE; +} + +curl_off_t curlx_uztoso(size_t uznum) +{ +#if SIZEOF_SIZE_T >= SIZEOF_CURL_OFF_T + if(uznum > (size_t)CURL_OFF_T_MAX) + return CURL_OFF_T_MAX; +#endif + return (curl_off_t)uznum; +} diff --git a/lib/curlx/warnless.h b/lib/curlx/warnless.h index 0a0c608073..a128f71488 100644 --- a/lib/curlx/warnless.h +++ b/lib/curlx/warnless.h @@ -57,6 +57,18 @@ unsigned short curlx_uitous(unsigned int uinum); size_t curlx_sitouz(int sinum); +size_t curlx_uitouz(unsigned int uinum); + +/* Convert a curl_off_t to fit into size_t interval [uzmin, uzmax]. + * values outside this interval give the lower/upper bound. */ +size_t curlx_sotouz_range(curl_off_t sonum, size_t uzmin, size_t uzmax); + +/* Convert a size_t to curl_off_t, return CURL_OFF_T_MAX if too large. */ +curl_off_t curlx_uztoso(size_t uznum); + +/* Convert a ssize_t to size_t, return FALSE if negative and set 0 */ +bool curlx_sztouz(ssize_t sznum, size_t *puznum); + #ifdef _WIN32 #undef read #define read(fd, buf, count) (ssize_t)_read(fd, buf, curlx_uztoui(count)) diff --git a/lib/dict.c b/lib/dict.c index 3296a45466..5c7ba7f622 100644 --- a/lib/dict.c +++ b/lib/dict.c @@ -160,9 +160,9 @@ static CURLcode sendf(struct Curl_easy *data, const char *fmt, ...) if(result) break; - Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written); + Curl_debug(data, CURLINFO_DATA_OUT, sptr, bytes_written); - if((size_t)bytes_written != write_len) { + if(bytes_written != write_len) { /* if not all was written at once, we must advance the pointer, decrease the size left and try again! */ write_len -= bytes_written; diff --git a/lib/http.c b/lib/http.c index 0555291d0b..f3444d46a9 100644 --- a/lib/http.c +++ b/lib/http.c @@ -2222,9 +2222,11 @@ static CURLcode set_reader(struct Curl_easy *data, Curl_HttpReq httpreq) result = Curl_creader_set_null(data); } else if(data->set.postfields) { - if(postsize > 0) - result = Curl_creader_set_buf(data, data->set.postfields, - (size_t)postsize); + size_t plen = curlx_sotouz_range(postsize, 0, SIZE_MAX); + if(plen == SIZE_MAX) + return CURLE_OUT_OF_MEMORY; + else if(plen) + result = Curl_creader_set_buf(data, data->set.postfields, plen); else result = Curl_creader_set_null(data); } diff --git a/lib/http2.c b/lib/http2.c index de1113c1e4..5c8b0cab38 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -45,6 +45,7 @@ #include "curlx/strparse.h" #include "transfer.h" #include "curlx/dynbuf.h" +#include "curlx/warnless.h" #include "headers.h" /* The last 3 #include files should be in this order */ @@ -539,10 +540,12 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf, * in the H1 request and we upgrade from there. This stream * is opened implicitly as #1. */ uint8_t binsettings[H2_BINSETTINGS_LEN]; - ssize_t binlen; /* length of the binsettings data */ + ssize_t rclen; + size_t binlen; /* length of the binsettings data */ - binlen = populate_binsettings(binsettings, data); - if(binlen <= 0) { + rclen = populate_binsettings(binsettings, data); + + if(!curlx_sztouz(rclen, &binlen) || !binlen) { failf(data, "nghttp2 unexpectedly failed on pack_settings_payload"); result = CURLE_FAILED_INIT; goto out; @@ -554,7 +557,7 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf, DEBUGASSERT(stream); stream->id = 1; /* queue SETTINGS frame (again) */ - rc = nghttp2_session_upgrade2(ctx->h2, binsettings, (size_t)binlen, + rc = nghttp2_session_upgrade2(ctx->h2, binsettings, binlen, data->state.httpreq == HTTPREQ_HEAD, NULL); if(rc) { @@ -627,16 +630,16 @@ static CURLcode h2_process_pending_input(struct Curl_cfilter *cf, { struct cf_h2_ctx *ctx = cf->ctx; const unsigned char *buf; - size_t blen; + size_t blen, nread; ssize_t rv; while(Curl_bufq_peek(&ctx->inbufq, &buf, &blen)) { rv = nghttp2_session_mem_recv(ctx->h2, (const uint8_t *)buf, blen); - if(rv < 0) { + if(!curlx_sztouz(rv, &nread)) { failf(data, "nghttp2 recv error %zd: %s", rv, nghttp2_strerror((int)rv)); return CURLE_HTTP2; } - Curl_bufq_skip(&ctx->inbufq, (size_t)rv); + Curl_bufq_skip(&ctx->inbufq, nread); if(Curl_bufq_is_empty(&ctx->inbufq)) { break; } @@ -1804,16 +1807,17 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req, size_t blen; struct SingleRequest *k = &data->req; uint8_t binsettings[H2_BINSETTINGS_LEN]; - ssize_t binlen; /* length of the binsettings data */ + ssize_t rc; + size_t binlen; /* length of the binsettings data */ - binlen = populate_binsettings(binsettings, data); - if(binlen <= 0) { + rc = populate_binsettings(binsettings, data); + if(!curlx_sztouz(rc, &binlen) || !binlen) { failf(data, "nghttp2 unexpectedly failed on pack_settings_payload"); curlx_dyn_free(req); return CURLE_FAILED_INIT; } - result = curlx_base64url_encode((const char *)binsettings, (size_t)binlen, + result = curlx_base64url_encode((const char *)binsettings, binlen, &base64, &blen); if(result) { curlx_dyn_free(req); @@ -2173,15 +2177,16 @@ out: return result; } -static ssize_t cf_h2_body_send(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct h2_stream_ctx *stream, - const void *buf, size_t blen, bool eos, - CURLcode *err) +static CURLcode cf_h2_body_send(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct h2_stream_ctx *stream, + const void *buf, size_t blen, bool eos, + size_t *pnwritten) { struct cf_h2_ctx *ctx = cf->ctx; - size_t nwritten; + CURLcode result; + *pnwritten = 0; if(stream->closed) { if(stream->resp_hds_complete) { /* Server decided to close the stream after having sent us a final @@ -2193,31 +2198,29 @@ static ssize_t cf_h2_body_send(struct Curl_cfilter *cf, "on closed stream with response", stream->id); if(eos) stream->body_eos = TRUE; - *err = CURLE_OK; - return (ssize_t)blen; + *pnwritten = blen; + return CURLE_OK; } /* Server closed before we got a response, this is an error */ infof(data, "stream %u closed", stream->id); - *err = CURLE_SEND_ERROR; - return -1; + return CURLE_SEND_ERROR; } - *err = Curl_bufq_write(&stream->sendbuf, buf, blen, &nwritten); - if(*err) - return -1; + result = Curl_bufq_write(&stream->sendbuf, buf, blen, pnwritten); + if(result) + return result; - if(eos && (blen == nwritten)) + if(eos && (blen == *pnwritten)) stream->body_eos = TRUE; if(eos || !Curl_bufq_is_empty(&stream->sendbuf)) { /* resume the potentially suspended stream */ int rv = nghttp2_session_resume_data(ctx->h2, stream->id); - if(nghttp2_is_fatal(rv)) { - *err = CURLE_SEND_ERROR; - return -1; - } + if(nghttp2_is_fatal(rv)) + return CURLE_SEND_ERROR; } - return (ssize_t)nwritten; + + return CURLE_OK; } static CURLcode h2_submit(struct h2_stream_ctx **pstream, @@ -2234,7 +2237,8 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream, nghttp2_data_provider data_prd; int32_t stream_id; nghttp2_priority_spec pri_spec; - ssize_t nwritten; + ssize_t rc; + size_t nwritten; CURLcode result = CURLE_OK; *pnwritten = 0; @@ -2244,10 +2248,10 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream, if(result) goto out; - nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, &result); - if(nwritten < 0) + rc = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, &result); + if(!curlx_sztouz(rc, &nwritten)) goto out; - *pnwritten = (size_t)nwritten; + *pnwritten = nwritten; if(!stream->h1.done) { /* need more data */ goto out; @@ -2321,8 +2325,9 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream, bodylen = len - *pnwritten; if(bodylen || eos) { - ssize_t n = cf_h2_body_send(cf, data, stream, body, bodylen, eos, &result); - if(n >= 0) + size_t n; + result = cf_h2_body_send(cf, data, stream, body, bodylen, eos, &n); + if(!result) *pnwritten += n; else if(result == CURLE_AGAIN) result = CURLE_OK; @@ -2347,7 +2352,6 @@ static CURLcode cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data, struct cf_h2_ctx *ctx = cf->ctx; struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data); struct cf_call_data save; - ssize_t nwritten; CURLcode result = CURLE_OK, r2; CF_DATA_SAVE(save, cf, data); @@ -2364,21 +2368,19 @@ static CURLcode cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data, * being able to flush stream->sendbuf. Make a 0-length write * to trigger flushing again. * If this works, we report to have written `len` bytes. */ + size_t n; DEBUGASSERT(eos); - nwritten = cf_h2_body_send(cf, data, stream, buf, 0, eos, &result); - CURL_TRC_CF(data, cf, "[%d] cf_body_send last CHUNK -> %zd, %d, eos=%d", - stream->id, nwritten, result, eos); - if(nwritten < 0) { + result = cf_h2_body_send(cf, data, stream, buf, 0, eos, &n); + CURL_TRC_CF(data, cf, "[%d] cf_body_send last CHUNK -> %d, %zu, eos=%d", + stream->id, result, n, eos); + if(result) goto out; - } *pnwritten = len; } else { - nwritten = cf_h2_body_send(cf, data, stream, buf, len, eos, &result); - CURL_TRC_CF(data, cf, "[%d] cf_body_send(len=%zu) -> %zd, %d, eos=%d", - stream->id, len, nwritten, result, eos); - if(nwritten >= 0) - *pnwritten = (size_t)nwritten; + result = cf_h2_body_send(cf, data, stream, buf, len, eos, pnwritten); + CURL_TRC_CF(data, cf, "[%d] cf_body_send(len=%zu) -> %d, %zu, eos=%d", + stream->id, len, result, *pnwritten, eos); } /* Call the nghttp2 send loop and flush to write ALL buffered data, diff --git a/lib/multi.c b/lib/multi.c index 1e24ce8c46..a47336457b 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -3879,10 +3879,10 @@ CURLcode Curl_multi_xfer_buf_borrow(struct Curl_easy *data, } if(!data->multi->xfer_buf) { - data->multi->xfer_buf = malloc((size_t)data->set.buffer_size); + data->multi->xfer_buf = malloc(curlx_uitouz(data->set.buffer_size)); if(!data->multi->xfer_buf) { - failf(data, "could not allocate xfer_buf of %zu bytes", - (size_t)data->set.buffer_size); + failf(data, "could not allocate xfer_buf of %u bytes", + data->set.buffer_size); return CURLE_OUT_OF_MEMORY; } data->multi->xfer_buf_len = data->set.buffer_size; @@ -3932,10 +3932,11 @@ CURLcode Curl_multi_xfer_ulbuf_borrow(struct Curl_easy *data, } if(!data->multi->xfer_ulbuf) { - data->multi->xfer_ulbuf = malloc((size_t)data->set.upload_buffer_size); + data->multi->xfer_ulbuf = + malloc(curlx_uitouz(data->set.upload_buffer_size)); if(!data->multi->xfer_ulbuf) { - failf(data, "could not allocate xfer_ulbuf of %zu bytes", - (size_t)data->set.upload_buffer_size); + failf(data, "could not allocate xfer_ulbuf of %u bytes", + data->set.upload_buffer_size); return CURLE_OUT_OF_MEMORY; } data->multi->xfer_ulbuf_len = data->set.upload_buffer_size; diff --git a/lib/sendf.c b/lib/sendf.c index 980fae23e6..655444a295 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -209,20 +209,7 @@ static size_t get_max_body_write_len(struct Curl_easy *data, curl_off_t limit) { if(limit != -1) { /* How much more are we allowed to write? */ - curl_off_t remain_diff; - remain_diff = limit - data->req.bytecount; - if(remain_diff < 0) { - /* already written too much! */ - return 0; - } -#if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T - else if(remain_diff > SSIZE_MAX) { - return SIZE_MAX; - } -#endif - else { - return (size_t)remain_diff; - } + return curlx_sotouz_range(limit - data->req.bytecount, 0, SIZE_MAX); } return SIZE_MAX; } @@ -678,11 +665,7 @@ static CURLcode cr_in_read(struct Curl_easy *data, } /* respect length limitations */ if(ctx->total_len >= 0) { - curl_off_t remain = ctx->total_len - ctx->read_len; - if(remain <= 0) - blen = 0; - else if(remain < (curl_off_t)blen) - blen = (size_t)remain; + blen = curlx_sotouz_range(ctx->total_len - ctx->read_len, 0, blen); } nread = 0; if(ctx->read_cb && blen) { @@ -1363,9 +1346,9 @@ static CURLcode cr_buf_resume_from(struct Curl_easy *data, /* already started reading? */ if(ctx->index) return CURLE_READ_ERROR; - if(offset <= 0) + boffset = curlx_sotouz_range(offset, 0, SIZE_MAX); + if(!boffset) return CURLE_OK; - boffset = (size_t)offset; if(boffset > ctx->blen) return CURLE_READ_ERROR; diff --git a/lib/setopt.c b/lib/setopt.c index 9f43b1b60d..338e94d1bb 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -1689,22 +1689,20 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, if(!ptr || s->postfieldsize == -1) result = Curl_setstropt(&s->str[STRING_COPYPOSTFIELDS], ptr); else { + size_t pflen; + if(s->postfieldsize < 0) return CURLE_BAD_FUNCTION_ARGUMENT; -#if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T - /* - * Check that requested length does not overflow the size_t type. - */ - else if(s->postfieldsize > SIZE_MAX) + pflen = curlx_sotouz_range(s->postfieldsize, 0, SIZE_MAX); + if(pflen == SIZE_MAX) return CURLE_OUT_OF_MEMORY; -#endif else { /* Allocate even when size == 0. This satisfies the need of possible later address compare to detect the COPYPOSTFIELDS mode, and to mark that postfields is used rather than read function or form data. */ - char *p = Curl_memdup0(ptr, (size_t)s->postfieldsize); + char *p = Curl_memdup0(ptr, pflen); if(!p) return CURLE_OUT_OF_MEMORY; else { diff --git a/lib/transfer.c b/lib/transfer.c index 6ae21e1a40..4c17cbb50d 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -82,6 +82,7 @@ #include "hsts.h" #include "setopt.h" #include "headers.h" +#include "curlx/warnless.h" /* The last 2 #include files should be in this order */ #include "curl_memory.h" @@ -189,53 +190,44 @@ CURLcode Curl_xfer_send_shutdown(struct Curl_easy *data, bool *done) * @param err error code in case of -1 return * @return number of bytes read or -1 for error */ -static ssize_t xfer_recv_resp(struct Curl_easy *data, - char *buf, size_t blen, - bool eos_reliable, - CURLcode *err) +static CURLcode xfer_recv_resp(struct Curl_easy *data, + char *buf, size_t blen, + bool eos_reliable, + size_t *pnread) { - size_t nread; + CURLcode result; DEBUGASSERT(blen > 0); + *pnread = 0; /* If we are reading BODY data and the connection does NOT handle EOF * and we know the size of the BODY data, limit the read amount */ if(!eos_reliable && !data->req.header && data->req.size != -1) { - curl_off_t totalleft = data->req.size - data->req.bytecount; - if(totalleft <= 0) - blen = 0; - else if(totalleft < (curl_off_t)blen) - blen = (size_t)totalleft; + blen = curlx_sotouz_range(data->req.size - data->req.bytecount, 0, blen); } else if(xfer_recv_shutdown_started(data)) { /* we already received everything. Do not try more. */ blen = 0; } - if(!blen) { - /* want nothing more */ - *err = CURLE_OK; - nread = 0; - } - else { - *err = Curl_xfer_recv(data, buf, blen, &nread); + if(blen) { + result = Curl_xfer_recv(data, buf, blen, pnread); + if(result) + return result; } - if(*err) - return -1; - if(nread == 0) { + if(*pnread == 0) { if(data->req.shutdown) { bool done; - *err = xfer_recv_shutdown(data, &done); - if(*err) - return -1; + result = xfer_recv_shutdown(data, &done); + if(result) + return result; if(!done) { - *err = CURLE_AGAIN; - return -1; + return CURLE_AGAIN; } } DEBUGF(infof(data, "sendrecv_dl: we are done")); } - return (ssize_t)nread; + return CURLE_OK; } /* @@ -264,7 +256,6 @@ static CURLcode sendrecv_dl(struct Curl_easy *data, read or we get a CURLE_AGAIN */ do { size_t bytestoread; - ssize_t nread; if(!is_multiplex) { /* Multiplexed connection have inherent handling of EOF and we do not @@ -288,9 +279,9 @@ static CURLcode sendrecv_dl(struct Curl_easy *data, } rcvd_eagain = FALSE; - nread = xfer_recv_resp(data, buf, bytestoread, is_multiplex, &result); - if(nread < 0) { - if(CURLE_AGAIN != result) + result = xfer_recv_resp(data, buf, bytestoread, is_multiplex, &blen); + if(result) { + if(result != CURLE_AGAIN) goto out; /* real error */ rcvd_eagain = TRUE; result = CURLE_OK; @@ -298,7 +289,7 @@ static CURLcode sendrecv_dl(struct Curl_easy *data, !data->req.resp_trailer) { DEBUGF(infof(data, "EAGAIN, download done, no trailer announced, " "not waiting for EOS")); - nread = 0; + blen = 0; /* continue as if we received the EOS */ } else @@ -306,7 +297,6 @@ static CURLcode sendrecv_dl(struct Curl_easy *data, } /* We only get a 0-length receive at the end of the response */ - blen = (size_t)nread; is_eos = (blen == 0); if(!blen && (conn->recv[FIRSTSOCKET] == Curl_cf_recv)) { @@ -899,8 +889,8 @@ CURLcode Curl_xfer_recv(struct Curl_easy *data, DEBUGASSERT(data->conn); DEBUGASSERT(data->set.buffer_size > 0); - if((size_t)data->set.buffer_size < blen) - blen = (size_t)data->set.buffer_size; + if(curlx_uitouz(data->set.buffer_size) < blen) + blen = curlx_uitouz(data->set.buffer_size); return Curl_conn_recv(data, data->conn->recv_idx, buf, blen, pnrcvd); } diff --git a/lib/vquic/curl_ngtcp2.c b/lib/vquic/curl_ngtcp2.c index 1f70e0b480..475060ebdd 100644 --- a/lib/vquic/curl_ngtcp2.c +++ b/lib/vquic/curl_ngtcp2.c @@ -1320,32 +1320,25 @@ static CURLcode init_ngh3_conn(struct Curl_cfilter *cf, return CURLE_OK; } -static ssize_t recv_closed_stream(struct Curl_cfilter *cf, +static CURLcode recv_closed_stream(struct Curl_cfilter *cf, struct Curl_easy *data, struct h3_stream_ctx *stream, - CURLcode *err) + size_t *pnread) { - ssize_t nread = -1; - (void)cf; + *pnread = 0; if(stream->reset) { failf(data, "HTTP/3 stream %" FMT_PRId64 " reset by server", stream->id); - *err = data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP3; - goto out; + return data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP3; } else if(!stream->resp_hds_complete) { failf(data, "HTTP/3 stream %" FMT_PRId64 " was closed cleanly, but before " "getting all response header fields, treated as error", stream->id); - *err = CURLE_HTTP3; - goto out; + return CURLE_HTTP3; } - *err = CURLE_OK; - nread = 0; - -out: - return nread; + return CURLE_OK; } /* incoming data frames on the h3 stream */ @@ -1393,9 +1386,7 @@ static CURLcode cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data, goto out; } else if(stream->closed) { - ssize_t nread = recv_closed_stream(cf, data, stream, &result); - if(nread > 0) - *pnread = (size_t)nread; + result = recv_closed_stream(cf, data, stream, pnread); goto out; } result = CURLE_AGAIN; diff --git a/lib/ws.c b/lib/ws.c index ddf49c9d2d..96a0d61378 100644 --- a/lib/ws.c +++ b/lib/ws.c @@ -41,6 +41,7 @@ #include "select.h" #include "curlx/nonblock.h" #include "curlx/strparse.h" +#include "curlx/warnless.h" /* The last 2 #include files should be in this order */ #include "curl_memory.h" @@ -489,12 +490,13 @@ static CURLcode ws_dec_pass_payload(struct ws_decoder *dec, size_t inlen; size_t nwritten; CURLcode result; - curl_off_t remain = dec->payload_len - dec->payload_offset; + size_t remain = curlx_sotouz_range(dec->payload_len - dec->payload_offset, + 0, SIZE_MAX); (void)data; while(remain && Curl_bufq_peek(inraw, &inbuf, &inlen)) { - if((curl_off_t)inlen > remain) - inlen = (size_t)remain; + if(inlen > remain) + inlen = remain; result = write_cb(inbuf, inlen, dec->frame_age, dec->frame_flags, dec->payload_offset, dec->payload_len, write_ctx, &nwritten); @@ -502,9 +504,10 @@ static CURLcode ws_dec_pass_payload(struct ws_decoder *dec, return result; Curl_bufq_skip(inraw, nwritten); dec->payload_offset += nwritten; - remain = dec->payload_len - dec->payload_offset; - CURL_TRC_WS(data, "passed %zu bytes payload, %" - FMT_OFF_T " remain", nwritten, remain); + remain = curlx_sotouz_range(dec->payload_len - dec->payload_offset, + 0, SIZE_MAX); + CURL_TRC_WS(data, "passed %zu bytes payload, %zu remain", + nwritten, remain); } return remain ? CURLE_AGAIN : CURLE_OK; @@ -651,16 +654,13 @@ static curl_off_t ws_payload_remain(curl_off_t payload_total, curl_off_t payload_offset, size_t payload_buffered) { - curl_off_t remain = payload_total - payload_offset; + curl_off_t buffered, remain = payload_total - payload_offset; if((payload_total < 0) || (payload_offset < 0) || (remain < 0)) return -1; -#if SIZEOF_SIZE_T >= SIZEOF_CURL_OFF_T - if(payload_buffered > (size_t)CURL_OFF_T_MAX) + buffered = curlx_uztoso(payload_buffered); + if(remain < buffered) return -1; -#endif - if(remain < (curl_off_t)payload_buffered) - return -1; - return remain - (curl_off_t)payload_buffered; + return remain - buffered; } static CURLcode ws_cw_dec_next(const unsigned char *buf, size_t buflen, @@ -947,7 +947,7 @@ static CURLcode ws_enc_write_payload(struct ws_encoder *enc, struct bufq *out, size_t *pnwritten) { CURLcode result; - size_t i, len, n; + size_t i, len, n, remain; *pnwritten = 0; if(Curl_bufq_is_full(out)) @@ -955,8 +955,9 @@ static CURLcode ws_enc_write_payload(struct ws_encoder *enc, /* not the most performant way to do this */ len = buflen; - if((curl_off_t)len > enc->payload_remain) - len = (size_t)enc->payload_remain; + remain = curlx_sotouz_range(enc->payload_remain, 0, SIZE_MAX); + if(remain < len) + len = remain; for(i = 0; i < len; ++i) { unsigned char c = buf[i] ^ enc->mask[enc->xori]; @@ -1167,8 +1168,7 @@ static CURLcode cr_ws_read(struct Curl_easy *data, if(ws->enc.payload_remain) { CURL_TRC_WS(data, "current frame, %" FMT_OFF_T " remaining", ws->enc.payload_remain); - if(ws->enc.payload_remain < (curl_off_t)blen) - blen = (size_t)ws->enc.payload_remain; + blen = curlx_sotouz_range(ws->enc.payload_remain, 0, blen); } result = Curl_creader_read(data, reader->next, buf, blen, &nread, &eos); -- 2.47.3