mirror of
https://github.com/X11Libre/xserver.git
synced 2026-01-27 14:24:09 +00:00
We don't really gain anything by calling `check_flip` early,
but it turns out that doing so causes problems.
Thanks to @jipok for finding this issue:
```
// gcc crash_x11libre.c -o crash_x11libre -lX11 -lXext -lXpresent
// Code written by LLM!
// WARNING: THIS PROGRAM IS INTENDED TO CRASH THE X SERVER (via XPresent + Glamor bug)
void attempt_crash_via_present(Display* dpy, Window win, int width, int height, int depth) {
XShmSegmentInfo shminfo;
// 1. Calculate TIGHT stride (width * 4 bytes).
// Misalignment here + XPresent is the killer combination.
int stride = width * 4;
size_t size = stride * height;
// 2. Resize the window to match the buffer (simulating JTK resize behavior)
XResizeWindow(dpy, win, width, height);
// XSync(dpy, False); // Optional: let window manager catch up, but hammering triggers races better
// 3. Allocate Shared Memory
memset(&shminfo, 0, sizeof(shminfo));
shminfo.shmid = shmget(IPC_PRIVATE, size, IPC_CREAT | 0777);
if (shminfo.shmid < 0) { perror("shmget"); return; }
shminfo.shmaddr = (char*)shmat(shminfo.shmid, 0, 0);
shminfo.readOnly = False;
shmctl(shminfo.shmid, IPC_RMID, 0); // Auto-cleanup
if (!XShmAttach(dpy, &shminfo)) {
fprintf(stderr, "XShmAttach failed\n");
shmdt(shminfo.shmaddr);
return;
}
// 4. Create the Misaligned Pixmap
Pixmap pixmap = XShmCreatePixmap(dpy, win, shminfo.shmaddr, &shminfo, width, height, depth);
// 5. THE TRIGGER: XPresentPixmap
// This forces Glamor to treat the SHM segment as a presentable surface.
// If strided alignment logic inside miCopyRegion/glamor is broken, this dies.
XPresentPixmap(dpy, win, pixmap, 0, 0, 0, 0, 0, None, None, None, 0, 0, 0, 0, 0, 0);
// Flush to make sure the server received the command
XSync(dpy, False);
// Cleanup for next iteration
XFreePixmap(dpy, pixmap);
XShmDetach(dpy, &shminfo);
shmdt(shminfo.shmaddr);
}
int main() {
Display* dpy = XOpenDisplay(NULL);
if (!dpy) { fprintf(stderr, "No display\n"); return 1; }
// Check extensions
int major, minor, pixmaps;
if (!XShmQueryVersion(dpy, &major, &minor, &pixmaps) || !pixmaps) {
fprintf(stderr, "XShm not supported!\n"); return 1;
}
int present_opcode, event_base, error_base;
if (!XQueryExtension(dpy, "Present", &present_opcode, &event_base, &error_base)) {
fprintf(stderr, "XPresent extension not supported! (Can't repro bug)\n");
return 1;
}
int screen = DefaultScreen(dpy);
XVisualInfo vinfo;
if (!XMatchVisualInfo(dpy, screen, 32, TrueColor, &vinfo)) {
printf("32-bit visual not found, using default.\n");
vinfo.visual = DefaultVisual(dpy, screen);
vinfo.depth = DefaultDepth(dpy, screen);
}
XSetWindowAttributes attrs;
attrs.colormap = XCreateColormap(dpy, RootWindow(dpy, screen), vinfo.visual, AllocNone);
attrs.background_pixel = 0; // Black
attrs.border_pixel = 0;
Window win = XCreateWindow(dpy, RootWindow(dpy, screen),
0, 0, 100, 100, 0,
vinfo.depth, InputOutput, vinfo.visual,
CWColormap | CWBackPixel | CWBorderPixel, &attrs);
XMapWindow(dpy, win);
XSync(dpy, False);
printf("Starting XPresent Stress Test...\n");
sleep(1);
// Fixed height (enough to have data), varying width
int height = 500;
// Iterate widths. We expect crashes on non-standard alignments.
// XLibre often crashes at 1266 width (stride 5064).
for (int w = 1000; w < 2000; w++) {
int stride = w * 4;
printf("\rTesting Width: %4d | Stride: %5d (mod 64: %2d)", w, stride, stride % 64);
fflush(stdout);
attempt_crash_via_present(dpy, win, w, height, vinfo.depth);
// Small delay to let the server actually try to process the Present request
// before we trash the memory, though XSync should handle it.
usleep(1000);
}
printf("\nTest finished successfully (No crash).\n");
XDestroyWindow(dpy, win);
XCloseDisplay(dpy);
return 0;
}
```
Fixes: https://github.com/X11Libre/xserver/issues/1754
Fixes: 9108a2bf55
Signed-off-by: stefan11111 <stefan11111@shitposting.expert>