summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Richardson <Alexander.Richardson@cl.cam.ac.uk>2021-06-16 14:50:51 +0100
committerAlan Coopersmith <alan.coopersmith@oracle.com>2021-06-27 18:35:02 +0000
commit1d5bb760ee996927dd5dfa5b3c219b3d6ef63d11 (patch)
tree1071deeada809c585fc4789324e5fe787eedc049
parentf8c7069a46af185e0bfaa43d63d450c9a44787ba (diff)
downloadxorg-lib-libXt-1d5bb760ee996927dd5dfa5b3c219b3d6ef63d11.tar.gz
Fix InternalCallbackRec layout if pointers are bigger than 64 bits
When running `xeyes` via `SSH -X` on CHERI-RISC-V FreeBSD, I was getting a Bus Error (unaligned store) in the `cl->callback = callback;` line of _XtAddCallback. The `cl` variable (created using `ToList(icl)`) was only aligned to 8 bytes, but for CHERI-RISC-V pointer-type loads and stores require 16-byte alignment. In order to fix this, I added a C99 flexible array member to internalCallbackRec when compiling for C99 or newer. This ensures that sizeof(InternalCallbackRec) is 16 (since it now includes the required 12 byte padding up to the first XtCallbackRec). This also ensures that alignof(InternalCallbackRec) is 16, but that doesn't matter in this case since malloc() will always return a sufficiently-aligned pointer. I also changed ToList(p) to use the flexible array member directly when compiling for C99. This is not a functional change since it will evaluate to the same pointer, but it does add additional type checking and ensures that only a `InternalCallbackRec *` can be passed to the macro. Signed-off-by: Alex Richardson <Alexander.Richardson@cl.cam.ac.uk>
-rw-r--r--include/X11/CallbackI.h6
-rw-r--r--src/Callback.c4
2 files changed, 9 insertions, 1 deletions
diff --git a/include/X11/CallbackI.h b/include/X11/CallbackI.h
index 5d958f4..7d9a689 100644
--- a/include/X11/CallbackI.h
+++ b/include/X11/CallbackI.h
@@ -62,7 +62,11 @@ typedef struct internalCallbackRec {
unsigned short count;
char is_padded; /* contains NULL padding for external form */
char call_state; /* combination of _XtCB{FreeAfter}Calling */
-#ifdef LONG64
+#if __STDC_VERSION__ >= 199901L
+ /* When compiling with C99 or newer, use a flexible member to ensure
+ * padding and alignment for sizeof(). */
+ XtCallbackRec callbacks[];
+#elif defined(LONG64)
unsigned int align_pad; /* padding to align callback list */
#endif
/* XtCallbackList */
diff --git a/src/Callback.c b/src/Callback.c
index 0c4ef5c..fa18436 100644
--- a/src/Callback.c
+++ b/src/Callback.c
@@ -80,7 +80,11 @@ static _Xconst _XtString XtNxtRemoveAllCallback = "xtRemoveAllCallback";
static _Xconst _XtString XtNxtCallCallback = "xtCallCallback";
/* However it doesn't contain a final NULL record */
+#if __STDC_VERSION__ >= 199901L
+#define ToList(p) ((p)->callbacks)
+#else
#define ToList(p) ((XtCallbackList) ((p)+1))
+#endif
static InternalCallbackList *
FetchInternalList(Widget widget,