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).
This commit is contained in:
Dmitry Verenitsin
2026-08-08 18:22:30 +03:00
committed by GitHub
parent 30cdb387ae
commit fb9f37b9c7
+4 -2
View File
@@ -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];
}
}