Commit fb9f37b9c7 for freeswitch.com
commit fb9f37b9c7869630ee52a3ae87399fbbf99ad74d
Author: Dmitry Verenitsin <morbit85@gmail.com>
Date: Sat Aug 8 20:22:30 2026 +0500
Merge commit from fork
Bound the XOR unmasking loop to `wsh->rplen` (payload only) instead of
`wsh->datalen`, which also covers the header and caused up to a 14-byte
OOB write past the frame payload in `wsh->buffer` using the
client-supplied mask key.
Tighten the size guard from `>` to `>=` to reserve 1 byte for the
trailing NUL written after the payload; a frame filling `buflen` exactly
otherwise NUL-wrote 1 byte past `wsh->buffer`.
Only reachable when `enable-websocket` is set in `mod_xml_rpc.conf.xml`
(off by default).
diff --git a/src/mod/xml_int/mod_xml_rpc/ws.c b/src/mod/xml_int/mod_xml_rpc/ws.c
index b660b644f6..59dfe16b5a 100644
--- a/src/mod/xml_int/mod_xml_rpc/ws.c
+++ b/src/mod/xml_int/mod_xml_rpc/ws.c
@@ -485,7 +485,8 @@ issize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
need = (wsh->plen - (wsh->datalen - need));
- if ((need + wsh->datalen) > (issize_t)wsh->buflen) {
+ /* Reserve 1 byte for the trailing NUL below. */
+ if ((need + wsh->datalen) >= (issize_t)wsh->buflen) {
/* too big - Ain't nobody got time fo' dat */
*oc = WSOC_CLOSE;
return ws_close(wsh, WS_DATA_TOO_BIG);
@@ -510,7 +511,8 @@ issize_t ws_read_frame(wsh_t *wsh, ws_opcode_t *oc, uint8_t **data)
if (mask && maskp) {
issize_t i;
- for (i = 0; i < wsh->datalen; i++) {
+ /* Unmask payload only. */
+ for (i = 0; i < wsh->rplen; i++) {
wsh->payload[i] ^= maskp[i % 4];
}
}