mirror of
https://github.com/curl/curl.git
synced 2026-04-12 12:21:42 +08:00
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
This commit is contained in:
parent
78a610cb83
commit
cb2bcb681f
@ -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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
96
lib/http2.c
96
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,
|
||||
|
||||
13
lib/multi.c
13
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;
|
||||
|
||||
25
lib/sendf.c
25
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;
|
||||
|
||||
|
||||
12
lib/setopt.c
12
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 {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
36
lib/ws.c
36
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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user