# SPDX-License-Identifier: MIT # # Security tests for RECORD extension vulnerabilities. import time import pytest from proto import record from xclient import Extension @pytest.fixture def record_xclient_swapped(xclient_swapped): """Provide a byte-swapped xclient with RECORD initialized.""" ext = xclient_swapped.query_extension(Extension.RECORD) if not ext: pytest.skip("RECORD extension not available") req = record.QueryVersionRequest(opcode=ext.opcode) xclient_swapped.send_request(req) xclient_swapped.recv_response(timeout=5.0) return xclient_swapped, ext.opcode class TestRecordCreateContext: """Tests for RECORD CreateContext/RegisterClients vulnerabilities.""" @pytest.mark.swapped_client @pytest.mark.asan def test_swap_create_register_integer_underflow( self, xserver, record_xclient_swapped ): """ CVE-2020-14362 / ZDI-CAN-11574: SwapCreateRegister() used stuff->length (attacker-controlled 16-bit wire field) instead of client->req_len for bounds checking nClients. With big requests or a carefully crafted length field, the subtraction ``stuff->length - header_size`` can underflow, allowing nClients to pass the check and causing OOB reads during client ID swapping. Fixed in commit 2902b78535ec ("Fix XRecordRegisterClients() Integer underflow"). """ conn, opcode = record_xclient_swapped ctx_id = conn.alloc_id() # Send CreateContext claiming many clients but with # minimal actual data. req = record.CreateContextRequest( opcode=opcode, context_id=ctx_id, client_ids=[0], # One client ID ranges_data=b"\x00" * 32, # One range (32 bytes) n_clients_override=100, # Claim 100 clients n_ranges_override=1, ) conn.send_request(req) time.sleep(0.5) assert xserver.is_alive, ( "Server crashed - integer underflow in SwapCreateRegister (CVE-2020-14362)" )