mirror of
https://github.com/curl/curl.git
synced 2026-04-14 00:51:42 +08:00
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
This commit is contained in:
parent
4cc476b37f
commit
a4d3c4e847
43
lib/ws.c
43
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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user