From: Stefan Eissing Date: Thu, 9 Oct 2025 09:23:42 +0000 (+0200) Subject: ws: fix some edge cases X-Git-Tag: rc-8_17_0-1~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a4d3c4e84720c3f2cb94fef1a4e680bb4b3e91a2;p=thirdparty%2Fcurl.git ws: fix some edge cases Fix edge cases around handling of pending send frames and encoding frames with size_t/curl_off_t possible flowy things. Reported-by: Joshua Rogers Closes #18965 --- diff --git a/lib/ws.c b/lib/ws.c index d3379c6502..6c8f07e177 100644 --- a/lib/ws.c +++ b/lib/ws.c @@ -647,6 +647,22 @@ static CURLcode ws_enc_add_cntrl(struct Curl_easy *data, return CURLE_OK; } +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; + if((payload_total < 0) || (payload_offset < 0) || (remain < 0)) + return -1; +#if SIZEOF_OFF_T <= SIZEOF_SIZE_T + if((curl_off_t)payload_buffered < 0) + return -1; +#endif + if(remain < (curl_off_t)payload_buffered) + return -1; + return remain - (curl_off_t)payload_buffered; +} + static CURLcode ws_cw_dec_next(const unsigned char *buf, size_t buflen, int frame_age, int frame_flags, curl_off_t payload_offset, @@ -658,11 +674,16 @@ static CURLcode ws_cw_dec_next(const unsigned char *buf, size_t buflen, struct Curl_easy *data = ctx->data; struct websocket *ws = ctx->ws; bool auto_pong = !data->set.ws_no_auto_pong; - curl_off_t remain = (payload_len - (payload_offset + buflen)); + curl_off_t remain; CURLcode result; (void)frame_age; *pnwritten = 0; + remain = ws_payload_remain(payload_len, payload_offset, buflen); + if(remain < 0) { + DEBUGASSERT(0); /* parameter mismatch */ + return CURLE_BAD_FUNCTION_ARGUMENT; + } if(auto_pong && (frame_flags & CURLWS_PING) && !remain) { /* auto-respond to PINGs, only works for single-frame payloads atm */ @@ -981,12 +1002,18 @@ static CURLcode ws_enc_add_pending(struct Curl_easy *data, result); goto out; } - /* our buffer should always be able to take in a control frame */ - DEBUGASSERT(n == ws->pending.payload_len); + if(n != ws->pending.payload_len) { + DEBUGASSERT(0); /* buffer should always be able to take all */ + CURL_TRC_WS(data, "ws_enc_cntrl(), error added only %zu/%zu payload,", + n, ws->pending.payload_len); + result = CURLE_SEND_ERROR; + goto out; + } + /* the frame should be complete now */ DEBUGASSERT(!ws->enc.payload_remain); + memset(&ws->pending, 0, sizeof(ws->pending)); out: - memset(&ws->pending, 0, sizeof(ws->pending)); return result; } @@ -1445,10 +1472,16 @@ static CURLcode ws_client_collect(const unsigned char *buf, size_t buflen, struct ws_collect *ctx = userp; struct Curl_easy *data = ctx->data; bool auto_pong = !data->set.ws_no_auto_pong; - curl_off_t remain = (payload_len - (payload_offset + buflen)); + curl_off_t remain; CURLcode result = CURLE_OK; *pnwritten = 0; + remain = ws_payload_remain(payload_len, payload_offset, buflen); + if(remain < 0) { + DEBUGASSERT(0); /* parameter mismatch */ + return CURLE_BAD_FUNCTION_ARGUMENT; + } + if(!ctx->bufidx) { /* first write */ ctx->frame_age = frame_age;