]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
websockets: check for negative payload lengths
authorStefan Eissing <stefan@eissing.org>
Mon, 15 Jan 2024 12:02:34 +0000 (13:02 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 16 Jan 2024 13:56:15 +0000 (14:56 +0100)
- 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
tests/data/DISABLED
tests/data/Makefile.inc
tests/data/test2307 [new file with mode: 0644]

index 81b48180ccfed144ed09a45b169ece3ef321c08f..78c1404699722f61b9a5cd6104875a7684fc5430 100644 (file)
--- 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"
index b077c67a0fc6add849968c81df848540e3f66f6b..a98dc85668338ed1ecde8f0bb8c3d8234b2d66f9 100644 (file)
@@ -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
index ab66fc4cc4c872ef9c2b8c10a451ad8eb02e14c0..64859632a119b4a9d054cb2b3a3f0420b951534c 100644 (file)
@@ -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 (file)
index 0000000..26b3309
--- /dev/null
@@ -0,0 +1,71 @@
+<testcase>
+<info>
+<keywords>
+WebSockets
+</keywords>
+</info>
+
+#
+# Sends a PING with overlong payload
+<reply>
+<data nocheck="yes" nonewline="yes">
+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%
+</data>
+# allow upgrade
+<servercmd>
+upgrade
+</servercmd>
+</reply>
+
+#
+# Client-side
+<client>
+# require debug for the forced CURL_ENTROPY
+<features>
+debug
+ws
+!hyper
+</features>
+<server>
+http
+</server>
+<name>
+WebSockets, overlong PING payload
+</name>
+<tool>
+lib2302
+</tool>
+<command>
+ws://%HOSTIP:%HTTPPORT/%TESTNUMBER
+</command>
+</client>
+
+#
+# PONG with no data and the 32 bit mask
+#
+<verify>
+<protocol nocheck="yes" nonewline="yes">
+GET /%TESTNUMBER HTTP/1.1\r
+Host: %HOSTIP:%HTTPPORT\r
+User-Agent: webbie-sox/3\r
+Accept: */*\r
+Upgrade: websocket\r
+Connection: Upgrade\r
+Sec-WebSocket-Version: 13\r
+Sec-WebSocket-Key: NDMyMTUzMjE2MzIxNzMyMQ==\r
+\r
+
+</protocol>
+# 23 == CURLE_WRITE_ERROR
+<errorcode>
+23
+</errorcode>
+</verify>
+</testcase>