From 01e754610df2195536c5b31c1e8df756480599d1 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Tue, 12 Sep 2023 22:55:37 -0700 Subject: Ensure XRenderInfo pointers are appropriately aligned While runnig some X11 applications on an Arm Morello platform I noticed bus errors inside xrender. XRenderInfo uses a single malloc call to allocate multiple objects in one single allocation and places those objects directly after the XRenderInfo object. However, these calculations do not ensure that this objects are sufficiently aligned. I noticed this because on Morello (and other CHERI-enabled architectures) pointers need to be strongly aligned. Instead of allocating a single block with potentially misaligned subsequent objects, this change uses seprate allocations for the four arrays. This is an alternative to https://gitlab.freedesktop.org/xorg/lib/libxrender/-/merge_requests/12 Signed-off-by: Alex Richardson --- src/Xrender.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/Xrender.c b/src/Xrender.c index 61a1139..1755f41 100644 --- a/src/Xrender.c +++ b/src/Xrender.c @@ -294,11 +294,21 @@ XRenderFindDisplay (Display *dpy) return dpyinfo; } +static void +XRenderFreeXRenderInfo (XRenderInfo *xri) +{ + Xfree(xri->format); + Xfree(xri->screen); + Xfree(xri->depth); + Xfree(xri->visual); + Xfree(xri); +} + static int XRenderCloseDisplay (Display *dpy, XExtCodes *codes _X_UNUSED) { XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy); - if (info && info->info) XFree (info->info); + if (info && info->info) XRenderFreeXRenderInfo (info->info); return XRenderExtRemoveDisplay (&XRenderExtensionInfo, dpy); } @@ -469,11 +479,8 @@ XRenderQueryFormats (Display *dpy) (rep.numVisuals < ((INT_MAX / 4) / sizeof (XRenderVisual))) && (rep.numSubpixel < ((INT_MAX / 4) / 4)) && (rep.length < (INT_MAX >> 2)) ) { - xri = Xmalloc (sizeof (XRenderInfo) + - (rep.numFormats * sizeof (XRenderPictFormat)) + - (rep.numScreens * sizeof (XRenderScreen)) + - (rep.numDepths * sizeof (XRenderDepth)) + - (rep.numVisuals * sizeof (XRenderVisual))); + /* Zero-initialize so that pointers are NULL if there is a failure. */ + xri = Xcalloc (1, sizeof (XRenderInfo)); rlength = ((rep.numFormats * sizeof (xPictFormInfo)) + (rep.numScreens * sizeof (xPictScreen)) + (rep.numDepths * sizeof (xPictDepth)) + @@ -498,13 +505,13 @@ XRenderQueryFormats (Display *dpy) } xri->major_version = async_state.major_version; xri->minor_version = async_state.minor_version; - xri->format = (XRenderPictFormat *) (xri + 1); + xri->format = Xcalloc(rep.numFormats, sizeof(XRenderPictFormat)); xri->nformat = (int) rep.numFormats; - xri->screen = (XRenderScreen *) (xri->format + rep.numFormats); + xri->screen = Xcalloc(rep.numScreens, sizeof(XRenderScreen)); xri->nscreen = (int) rep.numScreens; - xri->depth = (XRenderDepth *) (xri->screen + rep.numScreens); + xri->depth = Xcalloc(rep.numDepths, sizeof(XRenderDepth)); xri->ndepth = (int) rep.numDepths; - xri->visual = (XRenderVisual *) (xri->depth + rep.numDepths); + xri->visual = Xcalloc(rep.numVisuals, sizeof(XRenderVisual)); xri->nvisual = (int) rep.numVisuals; _XRead (dpy, (char *) xData, (long) rlength); format = xri->format; @@ -538,7 +545,7 @@ XRenderQueryFormats (Display *dpy) screen->subpixel = SubPixelUnknown; xPDepth = (xPictDepth *) (xScreen + 1); if (screen->ndepths > rep.numDepths) { - Xfree (xri); + XRenderFreeXRenderInfo(xri); Xfree (xData); _XEatDataWords (dpy, rep.length); UnlockDisplay (dpy); @@ -555,7 +562,7 @@ XRenderQueryFormats (Display *dpy) depth->visuals = visual; xVisual = (xPictVisual *) (xPDepth + 1); if (depth->nvisuals > rep.numVisuals) { - Xfree (xri); + XRenderFreeXRenderInfo (xri); Xfree (xData); _XEatDataWords (dpy, rep.length); UnlockDisplay (dpy); -- cgit v1.2.3