test/pyxtest: add test for ProcXIChangeCursor with window None

Currently crashes the X server

Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2246>
This commit is contained in:
Alan Coopersmith 2026-06-19 14:52:00 -07:00 • committed by Olivier Fourdan
commit bb13ee0410
2 changed files with 49 additions and 1 deletions

View file

@ -11,6 +11,7 @@ XChangeDeviceProperty = 37
XGetDeviceProperty = 39
# XI2 minor opcodes
XIChangeCursor = 42
XIQueryVersion = 47
XIPassiveGrabDevice = 54
XIPassiveUngrabDevice = 55
@ -75,6 +76,28 @@ class XIQueryVersionRequest:
)
@dataclass
class XIChangeCursorRequest:
"""XIChangeCursor request."""
opcode: int
window: int
cursor: int
deviceid: int = XIAllMasterDevices
def to_bytes(self, byte_order: str = "<") -> bytes:
return struct.pack(
f"{byte_order}BBH II HH",
self.opcode,
XIChangeCursor,
4,
self.window,
self.cursor,
self.deviceid,
0, # pad
)
@dataclass
class XIPassiveGrabDeviceRequest:
"""XIPassiveGrabDevice request."""

View file

@ -7,7 +7,7 @@ import struct
import pytest
from proto import xi
from xclient import BadLength, BadValue, Extension, X11Error, X11Reply
from xclient import BadLength, BadWindow, BadValue, Extension, X11Error, X11Reply
@pytest.fixture
@ -389,3 +389,28 @@ class TestXIChangeDeviceControl:
"ChangeDeviceControl returned BadValue - "
"resolution values not byte-swapped"
)
class TestXIChangeCursor:
def test_change_cursor_null_window(self, xserver, xi_xclient):
"""
XIChangeCursor dereferences pWin even if it's not set
"""
opcode = xi_xclient.query_extension(Extension.XI).opcode
req = xi.XIChangeCursorRequest(
opcode=opcode,
window=0,
cursor=0,
deviceid=xi.VirtualCorePointer,
)
xi_xclient.send_request(req)
resp = xi_xclient.recv_response(timeout=5.0)
assert xserver.is_alive, "Server crashed"
# Without the fix: SegFault on a NULL WindowPtr
# With the fix: BadWindow
assert isinstance(resp, X11Error), f"Expected an error, got {resp}"
assert resp.error_code == BadWindow, (
"ChangeCursor didn't return BadWindow for Window 0"
)