mirror of
https://github.com/curl/curl.git
synced 2026-08-25 02:53:32 +03: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
1 changed files with 38 additions and 5 deletions
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;
|
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,
|
static CURLcode ws_cw_dec_next(const unsigned char *buf, size_t buflen,
|
||||||
int frame_age, int frame_flags,
|
int frame_age, int frame_flags,
|
||||||
curl_off_t payload_offset,
|
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 Curl_easy *data = ctx->data;
|
||||||
struct websocket *ws = ctx->ws;
|
struct websocket *ws = ctx->ws;
|
||||||
bool auto_pong = !data->set.ws_no_auto_pong;
|
bool auto_pong = !data->set.ws_no_auto_pong;
|
||||||
curl_off_t remain = (payload_len - (payload_offset + buflen));
|
curl_off_t remain;
|
||||||
CURLcode result;
|
CURLcode result;
|
||||||
|
|
||||||
(void)frame_age;
|
(void)frame_age;
|
||||||
*pnwritten = 0;
|
*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) {
|
if(auto_pong && (frame_flags & CURLWS_PING) && !remain) {
|
||||||
/* auto-respond to PINGs, only works for single-frame payloads atm */
|
/* 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);
|
result);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
/* our buffer should always be able to take in a control frame */
|
if(n != ws->pending.payload_len) {
|
||||||
DEBUGASSERT(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);
|
DEBUGASSERT(!ws->enc.payload_remain);
|
||||||
|
memset(&ws->pending, 0, sizeof(ws->pending));
|
||||||
|
|
||||||
out:
|
out:
|
||||||
memset(&ws->pending, 0, sizeof(ws->pending));
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1445,10 +1472,16 @@ static CURLcode ws_client_collect(const unsigned char *buf, size_t buflen,
|
||||||
struct ws_collect *ctx = userp;
|
struct ws_collect *ctx = userp;
|
||||||
struct Curl_easy *data = ctx->data;
|
struct Curl_easy *data = ctx->data;
|
||||||
bool auto_pong = !data->set.ws_no_auto_pong;
|
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;
|
CURLcode result = CURLE_OK;
|
||||||
|
|
||||||
*pnwritten = 0;
|
*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) {
|
if(!ctx->bufidx) {
|
||||||
/* first write */
|
/* first write */
|
||||||
ctx->frame_age = frame_age;
|
ctx->frame_age = frame_age;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue