From 49ca84144edf979007f50b2bb16e3c21319ccf3c Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Mon, 15 Jan 2024 13:02:34 +0100 Subject: [PATCH] websockets: check for negative payload lengths - in en- and decoding, check the websocket frame payload lengths for negative values (from curl_off_t) and error the operation in that case - add test 2307 to verify Closes #12707 --- lib/ws.c | 11 +++++++ tests/data/DISABLED | 2 ++ tests/data/Makefile.inc | 2 +- tests/data/test2307 | 71 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 tests/data/test2307 diff --git a/lib/ws.c b/lib/ws.c index 81b48180cc..78c1404699 100644 --- a/lib/ws.c +++ b/lib/ws.c @@ -225,6 +225,10 @@ static CURLcode ws_dec_read_head(struct ws_decoder *dec, dec->payload_len = (dec->head[2] << 8) | dec->head[3]; break; case 10: + if(dec->head[2] > 127) { + failf(data, "WS: frame length longer than 64 signed not supported"); + return CURLE_RECV_ERROR; + } dec->payload_len = ((curl_off_t)dec->head[2] << 56) | (curl_off_t)dec->head[3] << 48 | (curl_off_t)dec->head[4] << 40 | @@ -410,6 +414,13 @@ static ssize_t ws_enc_write_head(struct Curl_easy *data, size_t hlen; ssize_t n; + if(payload_len < 0) { + failf(data, "WS: starting new frame with negative payload length %" + CURL_FORMAT_CURL_OFF_T, payload_len); + *err = CURLE_SEND_ERROR; + return -1; + } + if(enc->payload_remain > 0) { /* trying to write a new frame before the previous one is finished */ failf(data, "WS: starting new frame with %zd bytes from last one" diff --git a/tests/data/DISABLED b/tests/data/DISABLED index b077c67a0f..a98dc85668 100644 --- a/tests/data/DISABLED +++ b/tests/data/DISABLED @@ -81,6 +81,8 @@ 2301 2302 2305 +# response body seem not to be handled by hyper +2307 %endif 2043 # The CRL test (313) doesn't work with rustls because rustls doesn't support diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc index ab66fc4cc4..64859632a1 100644 --- a/tests/data/Makefile.inc +++ b/tests/data/Makefile.inc @@ -244,7 +244,7 @@ test2100 \ \ test2200 test2201 test2202 test2203 test2204 test2205 \ \ -test2300 test2301 test2302 test2303 test2304 test2305 test2306 \ +test2300 test2301 test2302 test2303 test2304 test2305 test2306 test2307 \ \ test2400 test2401 test2402 test2403 test2404 \ \ diff --git a/tests/data/test2307 b/tests/data/test2307 new file mode 100644 index 0000000000..26b3309a8d --- /dev/null +++ b/tests/data/test2307 @@ -0,0 +1,71 @@ + + + +WebSockets + + + +# +# Sends a PING with overlong payload + + +HTTP/1.1 101 Switching to WebSockets +Server: test-server/fake +Upgrade: websocket +Connection: Upgrade +Something: else +Sec-WebSocket-Accept: HkPsVga7+8LuxM4RGQ5p9tZHeYs= + +%hex[%19%7f%ff%30%30%30%30%30%30%30%30%30%30%30%30]hex% + +# allow upgrade + +upgrade + + + +# +# Client-side + +# require debug for the forced CURL_ENTROPY + +debug +ws +!hyper + + +http + + +WebSockets, overlong PING payload + + +lib2302 + + +ws://%HOSTIP:%HTTPPORT/%TESTNUMBER + + + +# +# PONG with no data and the 32 bit mask +# + + +GET /%TESTNUMBER HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +User-Agent: webbie-sox/3 +Accept: */* +Upgrade: websocket +Connection: Upgrade +Sec-WebSocket-Version: 13 +Sec-WebSocket-Key: NDMyMTUzMjE2MzIxNzMyMQ== + + + +# 23 == CURLE_WRITE_ERROR + +23 + + +