summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Richardson <arichardson@FreeBSD.org>2023-09-12 22:55:37 -0700
committerAlex Richardson <arichardson@FreeBSD.org>2023-09-12 23:18:50 -0700
commit01e754610df2195536c5b31c1e8df756480599d1 (patch)
tree84ce877cb7f5885384fdba2dd05a0008749c180f
parent07efd80468f6b595e6432edd28b8560ca7695ba0 (diff)
Ensure XRenderInfo pointers are appropriately alignedHEADmaster
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 <arichardson@FreeBSD.org>
-rw-r--r--src/Xrender.c31
1 files 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);