We make two glyphsets, GS1 and GS2, both with the same format depth.
GS1 contains any glyph different from the others, let's call it U
(unique). GS2 contains two glyphs with the same content, or at least
sha1 hash. Let's call them A and B.
We first register GS1 and GS2. GS1 has no problems, but before the
fix, registering GS2 breaks accounting in `globalGlyphs`. Since there
is no check for duplicate glyphs within a single set, we make two
`GlyphNew` entries for A and B. Now in the loop at the end, we go over
each entry and call `AddGlyph` and `FreeGlyph`:
1. AddGlyph(GS2, A, idA) inserts A into `globalGlyphs`
2. FreeGlyph(A) drops A's refcnt by one, but as it's being held in
`globalGlyphs` it's kept alive.
3. AddGlyph(GS2, B, idB) finds A in `globalGlyphs` and reuses it
instead of inserting B
4. FreeGlyph(B) drops B's refcnt by one (to zero), and B is freed.
Before the fix, the lookup in `globalGlyphs` finds A's entry, and
since it isn't a DeletedGlyph, it erroneously removes the
`gr->glyph` pointing to `A` and decrements `tableEntries`. This
results in `tableEntries` being off-by-one as `A` is still alive.
Now, we free the glyphsets in a particular order. Freeing GS1 results
in calling FreeGlyph(U), which will decrement U's refcnt to zero, and
free U. This clears out the entry in `globalGlyphs` for U and
decrements `tableEntries`, which due to the earlier error is now zero.
When `FreeGlyphSet` sees this, it clears the `globalGlyphs` for that
format depth. Now freeing A or GS2 (which transitively frees A) will
try to check the `globalGlyphs` at that format depth, but because it
was cleared out this crashes.
The fix here is to change FreeGlyph to only free a glyph from
`globalGlyphs` that is exactly the glyph being freed, so that
FreeGlyph(B) doesn't touch `globalGlyphs` at all. This keeps a proper
count in `tableEntries` and prevents `globalGlyphs[fdepth]` from being
freed before A is freed.
Closes: #1881
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2264>
(cherry picked from commit 81edc9caf557f7a44c5b308742814457de0eb6c0)
(cherry picked from commit 716d876142280cd66bdcf000f81428dadd5d3937)
Signed-off-by: Octavia Togami <octy@octyl.net>
XIQueryDevice already reports the current cumulative axisVal for relative scroll valuators. Seed nonzero vertical and horizontal values and verify their FP3232 representation for native and swapped clients.
Signed-off-by: Lukáš Lipinský <18076-Mr-Tao@users.noreply.gitlab.freedesktop.org>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2292>
(cherry picked from commit 18dbde8971)
(cherry picked from commit 1688dcf08ee721db3b336677d0530b824b6b43a0)
(cherry picked from commit 7c7748e311ea9ad00d9c71e3d00a7a259d77473d)
This reverts commit b799d88a78.
Breaks CI. We'll have to do some more things, until we can
actually merge that.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Set locale to C before checking log message format to ensure consistent
behavior across all locales. The test was checking for 'en\n' at the end
of log messages, which only works in English locale.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
This allows tests to use an xserver_args fixture/parameter to pass
arguments for the xserver fixture they may use.
Assisted-by: Claude:claude-opus-4-6
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2263>
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
SDeviceChangedEvent left ValuatorClass.value and every ScrollClass-specific multi-byte field in server byte order. Swapped clients therefore received corrupt current values and scroll metadata.
Swap those fields and extend the protocol event conversion coverage to nonzero relative valuator values and both scroll directions and flags.
Signed-off-by: Lukáš Lipinský <18076-Mr-Tao@users.noreply.gitlab.freedesktop.org>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2291>
(cherry picked from commit cf91b97d6c)
(cherry picked from commit 7a7e9c66b17cd0d64d31fa19244f3e4eb162fed7)
(cherry picked from commit f9e486ad1d398fb8dcf48f88cd8923decd291c7c)
SwapScrollInfo converted the other multi-byte ScrollClass fields but left flags in server byte order. Swap it as well and decode the field in the swapped-client protocol test so nonzero flags exercise the wire representation.
Signed-off-by: Lukáš Lipinský <18076-Mr-Tao@users.noreply.gitlab.freedesktop.org>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2291>
(cherry picked from commit 8033c4d93e)
(cherry picked from commit 2d1d0b67dc2119507f52e3dae96827b8946d0eca)
(cherry picked from commit db6f28acaa7c7d2a049a92396e1bc35b6f759d8a)
When a later test child is killed by a signal, exit_code may still contain zero from the preceding child. Return EXIT_FAILURE explicitly so Meson cannot report a false success.
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2293>
(cherry picked from commit 495ea74203)
(cherry picked from commit 21e4929c355df7f525d0d0299781ccb6daa83780)
(cherry picked from commit d9abd1140755adcee1e2c9ec6d53794fb276f8d1)
Signed-off-by: Lukáš Lipinský <18076-Mr-Tao@users.noreply.gitlab.freedesktop.org>
Send a swapped ChangeDeviceControl/DEVICE_RESOLUTION with
num_valuators=255 and no valuator payload. Without the SProc length
check this overruns the request buffer; with it the server returns
BadLength.
Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2285>
(cherry picked from commit ddf3edc368)
(cherry picked from commit 3ed09c52d4a9cfe85b5f9d2f64beac022d79b221)
(cherry picked from commit 3f8dfe0169d563e147872a659ff461b95eeea16b)
The X11 core protocol error code constants (BadRequest, BadValue,
BadWindow, etc.) belong with the other protocol definitions in
proto/x11.py rather than in the client connection module.
Move the canonical definitions to proto/x11.py and re-export them from
xclient.py for backward compatibility. Update all test files to import
from proto.x11 instead.
Assisted-by: Claude:claude-opus-4-6
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2263>
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
At this point, allowing X Font Server connections just introduces us to
possible security issues since the code effectively trusts any font
server and few checks are in place.
Since font servers also haven't been used for ages, let's disable
them by default. Use-cases that require them will have to pass
+fontserverconnections on the commandline and/or set the corresponding
ServerFlags option.
The tests are a bit hacky: Debian builds libXfont2 with --disable-fc so
we need to cater for the case where the X server enables fontserver support
but libXfont then blocks it and we still need to treat this as success.
Assisted-by: Claude:claude-opus-4-6
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2263>
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Add xf86DoInterpretHDRMetadata(), which walks the EDID's CTA/CEA
extension data blocks and fills in a new struct monitor_hdr_data
(tail-appended field xf86Monitor::hdr) from the two blocks a display
uses to advertise HDR support:
- the Colorimetry Data Block (tag 5): which extended gamuts/transfer
spaces the display accepts (BT.2020 RGB/YCC/cYCC, opRGB, xvYCC,
ICtCp, ...), exposed via is_CTA_CDB_*() bit-test macros.
- the HDR Static Metadata Data Block (tag 6): supported EOTFs
(traditional SDR/HDR gamma, SMPTE ST.2084/PQ, HLG) plus the
desired content min/max/max-frame-average luminance, decoded with
the CTA-861-G power-law formulas.
Covered by a new EDID unit test (test/ddc-tests.c) using real captured
EDIDs from four displays (Samsung Q800T, MSI MAG321CURV, HP 27 QD, and
a QEMU virtual display as the "no HDR block present" negative case),
asserting the parsed colorimetry/luminance values match known-good
figures for each.
This is a standalone prerequisite for HDR support, independent of any
particular rendering-pipeline design: cepelinas9000's HDR work
(https://github.com/cepelinas9000/xserver/tree/wip/x11hdrV2) needs to
know a display's HDR/colorimetry capabilities before doing anything
else, and this is useful on its own for any HDR/wide-gamut detection
regardless of how the rest of the pipeline ends up looking.
Extracted (with typo/whitespace cleanup, no logic changes) from
cepelinas9000's wip/x11hdrV2 branch, commit 159a6f484a, for standalone
review ahead of the larger HDR effort.
Note for review: struct monitor_hdr_data is added as a new field at
the tail of the public xf86Monitor struct (include/edid.h) - additive
only, no existing field shifts.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Update SPDX-License-Identifier from MIT OR X11 (or MIT OR X11 OR AGPLv3+ variants)
to the canonical X11 OR MIT OR AGPL-3.0-or-later on 95 existing source files.
Add the triple-license header to 33 newly-identified files authored by Enrico
Weigelt that were missing SPDX headers entirely.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
XF86-BigFont lets local clients share font-metrics arrays via SysV
shared memory (and compresses them for remote clients) -- a local-only
optimization dating back to ancient XFree86. It hasn't been built by
default for really long time.
Enabling it in our CI immediately exposed that the code has bit-rotted
on 7 non-Linux CI lanes (macOS/BSD: including a nonexistent Linux-only
header; Solaris: an ARRAY_SIZE redefinition pulled in via its system
headers; mingw32: implicit geteuid()/getegid() plus an unused variable).
Concrete evidence that this extension currently has no real users
exercising it, since none of that breakage was ever noticed.
Therefore no practical need for carrying it around any longer.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
GLYPHWIDTHPIXELS and GLYPHHEIGHTPIXELS compute glyph dimensions from
signed INT16 fields. A crafted PCF font can produce negative results
(e.g. rightSideBearing < leftSideBearing).
All callees have a while (height--) loop which will end up in OOB writes
for negative height values.
In the case of a negative height, some callees cast to size_t or end up
with negative strides.
The same pattern exists in fbPoloyGlyphBit, miPolyGlyphBlt and
glamor_poly_glyph_blt_gl, so let's fix all of them in one go.
Assisted-by: Claude:claude-opus-4-6
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2250>
(cherry picked from commit e31efd3e10)
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
glamor_font_get() computes the atlas slot size from the font's declared
maxbounds, but copies each glyph's bitmap using the per-glyph metrics
(GLYPHHEIGHTPIXELS/GLYPHWIDTHBYTES macros). When a malicious PCF font
has per-glyph metrics exceeding maxbounds, the memcpy writes past the
heap-allocated atlas buffer. Negative per-glyph metrics are even worse:
the loop counter wraps to ~4 billion iterations (via unsigned cast) or
memcpy's size parameter wraps to SIZE_MAX.
The PCF parser in libXfont2 does not recompute maxbounds from per-glyph
data (only the BDF parser does), so the file's declared maxbounds values
are trusted as-is.
Reject fonts where any per-glyph metric is negative or exceeds the
atlas slot size, falling back to software rendering which uses per-glyph
metrics directly without an atlas.
This vulnerability was discovered by:
Anonymous working with Trend Micro Zero Day Initiative
CVE-2026-55999/ZDI-CAN-30498
Assisted-by: Claude:claude-opus-4-6
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2250>
(cherry picked from commit fbf7bac22e)
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
oldTag in CommonMakeCurrent() is a pointer to cl->contextTags[...].
CommonMakeCurrent() may realloc(cl->contextTags) and thus move the
memory, leaving oldTag as dangling pointer.
If we then GlxFreeContextTag(oldTag) we end up writing into freed
memory.
Fix this by freeing oldTag before CommonMakeNewCurrent().
This vulnerability was discovered by:
Anonymous working with Trend Micro Zero Day Initiative
CVE-2026-56000/ZDI-CAN-30561
Fixes: 4781f2a5a8 ("GLX: Free the tag of the old context later")
Assisted-by: Claude:claude-opus-4-6
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2250>
(cherry picked from commit 2779affbdb)
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Add a dedicated xserver-build-ubuntu-valgrind job that builds a debug
Xvfb and runs the pyxtest suite (test/pyxtest/) with --valgrind, so
memory errors (invalid reads/writes, use-after-free, uninitialised
value use) are caught in CI, not just OOB bugs ASAN happens to catch
locally.
The pytest-based harness (test/pyxtest/conftest.py, xserver.py,
valgrind.py) already implements valgrind support; it was simply never
wired into CI. pytest itself was also not installed in the Ubuntu CI
image, so the existing pyxtest suite has been silently skipped (not
built, since meson's find_program('pytest', required: false) found
nothing) on every other Ubuntu lane too. Installing python3-pytest
fixes that as a side effect: the normal xserver-build-ubuntu* jobs now
also actually run pyxtest (without valgrind) as part of "meson test",
exercising the existing protocol-fuzzing regression tests that were
previously dead weight.
Kept as a separate lane rather than adding --valgrind to the existing
run-xserver-build-and-test.sh: valgrind is slow, and pyxtest only
needs Xvfb, not the full Xorg/Xephyr/Xnest/XTS/piglit build the other
lanes carry.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
run_test_in_child() now checks XLIBRE_TEST (a comma-separated list of
suite function names, e.g. "ddc_tests,xkb_test") and skips any suite
not named in it. Unset/empty behaves exactly as before (run
everything).
Handy for iterating on a single new test suite without wading through
the rest of test/tests' output every run, and for isolating one
suite when an unrelated one in the sequence is flaky (run_test_in_child
exit()s the whole binary on the first failing suite, so a single flaky
suite ahead of the one you care about currently blocks everything
after it).
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
The bigreq request-length test ignored the return value of the write()
that sends the hand-built request, which gcc flags as -Werror=unused-result
(seen on the gentoo lane once -Dwerror is enabled). Treat a short/failed
write as the "something else went wrong" case (return 2) — the test can't
have exercised the bug if the request never went out.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Move the actual body of WriteToClient() into a new internal worker
dixWriteToClient() and turn WriteToClient() into a thin exported
frontend that just delegates to it.
This separates the two roles the function had: the exported, legacy
entry point kept for ABI compatibility with out-of-tree drivers/modules,
and the worker used by all in-tree reply/event paths. In-tree callers
will be moved over to dixWriteToClient() in the following commits, which
also lets the frontend be instrumented later without affecting internal
paths.
dixWriteToClient() is declared in the private os/io_priv.h but still
exported (_X_EXPORT), since in-tree modules that may be built as separate
shared objects (e.g. GLX) need to link against it.
The xi1/xi2 protocol unit tests intercept the reply path via
-Wl,-wrap,WriteToClient. As the in-tree reply path moves onto
dixWriteToClient(), retarget the linker wrap (and the WRAP_FUNCTION /
wrapped_* references) to dixWriteToClient(); this also covers calls that
still go through the WriteToClient() frontend, since it funnels into the
same worker.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
PR: https://github.com/X11Libre/xserver/pull/3162
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
On Solaris, to get information about the process on the other side of
a socket, we use the getpeerucred() system call instead of the
SO_PEERCRED socket option.
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2241>
Replace public min/max macros by private MIN/MAX and deprecate them.
The few drivers still using them can trivially define them on their own.
Adding a new private header for all kind of math-ish definitions - future
commits will move more stuff there.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Add regression tests for xorg_list operations on a *zero-initialized*
list head (next == prev == NULL), i.e. a head embedded in a calloc()'d
struct that was never run through xorg_list_init().
Covers the paths hardened in the preceding commit, so the gap found while
repairing #1639 (a never-init'd client->saveSets crashing
DeleteWindowFromAnySaveSet() via xorg_list_for_each_entry_safe()) cannot
silently regress:
- xorg_list_del() on a zeroed head (the documented "reset to empty list")
- xorg_list_for_each_entry_safe() over a zeroed/empty head
- add + safe-delete drain starting from a zeroed head
Without the macro fix these dereference NULL and crash; run_test_in_child()
forks per test, so the crash surfaces as a unit-test failure (verified: the
test fails at both -O0 and -O2 on the pre-fix tree, passes with the fix).
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
For safety, add extra parantheses on each used macro argument.
In most cases not strictly necessary, but better have some strict
and automatically enforcable policy here than wasting time on
judging individual cases.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Add TestScreenSaverFreeAttr which exercises the ScreenSaverFreeAttr
code path by setting attributes, activating the screen saver, then
closing the client connection (triggering resource cleanup).
While ScreenSaverFreeAttr currently does not dereference pPriv after
CheckScreenPrivate, this test verifies the code path is safe and
would catch regressions if future code changes introduced a stale
pointer dereference (same pattern as ZDI-CAN-30168).
Assisted-by: Claude:claude-opus-4-6
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2228>
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Add ListFonts, SetFontPath, and GetFontPath protocol builders to
proto/x11.py and a regression test that reproduces the
doListFontsAndAliases stack buffer overflow.
The test creates a temporary font directory with a fonts.alias file
containing an alias whose target name is 400 bytes -- exceeding the
old XLFDMAXFONTNAMELEN of 256 but under libXfont2's MAXFONTNAMELEN of
1024. It prepends this directory to the font path via SetFontPath, then
sends ListFonts matching the alias name. Without the fix, the server
would copy the oversized resolved name into a 256-byte stack buffer,
causing a stack buffer overflow.
ZDI-CAN-30136
Assisted-by: Claude:claude-opus-4-6
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2228>
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Add a regression test that reproduces the mapWidths stack buffer overflow
in CheckKeyTypes.
The test sends two XkbSetMap requests: first with firstType=0, nTypes=255,
ResizeTypes to expand the type table to 255 entries, then with
firstType=255, nTypes=10, ResizeTypes. The second request passes the
firstType > num_types check (255 > 255 is false) and computes
nMaps = 255 + 10 = 265. Without the fix, the loop would write
mapWidths[255..264], overflowing 9 bytes past the 256-element stack
buffer into adjacent stack variables.
Assisted-by: Claude:claude-opus-4-6
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2228>
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
Add a regression test that reproduces the XKB num_levels stack overflow.
The test sends an XkbSetMap request with XkbSetMapResizeTypes that includes
a non-canonical key type with numLevels=255, exceeding XkbMaxShiftLevel
(63). Without the fix, this type would be accepted and stored in the
server's type table. A subsequent ChangeKeyboardMapping would trigger
XkbUpdateKeyTypesFromCore -> XkbKeyTypesForCoreSymbols, where the
oversized num_levels is used as groupsWidth, causing indices into the
tsyms[252] stack buffer to reach up to 1019 and overflow.
Assisted-by: Claude:claude-opus-4-6
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2228>
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>