ws: fix some edge cases
No binary (build failed)
—
(log yok)
| @@ -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; | |