Skip to content

Conversation

@onitake
Copy link

@onitake onitake commented Dec 25, 2025

Fixes: #20473

This PR replaces the static upcasting in the helper macros _READ and _WRITE with a memcpy call.

Some of the functions in librt_internal.c use these macros to write 16 or 32 bit integer values, while the data->ptr is byte-aligned and may point to a memory address that is not divisible by 2 or 4.
This leads to a crash (with SIGBUS) on CPU architectures that have strict memory alignment, or possibly a performance penalty on others.

By replacing the direct assignment with memcpy, the compiler will figure out the most optimal method to access the unaligned memory.
I analyzed the resulting machine code generated by gcc 15 on amd64 and sparc64: The memcpy call was in fact optimized away, with instructions that avoided the crash on sparc64. On amd64, it made no difference performance-wise (compared to the original code).

#define _READ(result, data, type) \
do { \
*(result) = *(type *)(((ReadBufferObject *)data)->ptr); \
memcpy((void *) result, ((ReadBufferObject *)data)->ptr, sizeof(type)); \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spacing between the cast and variable is inconsistent:

(void *) result vs (ReadBufferObject *)data. Since the previous code uses no spacing here, I suggest changing it to (void *)result.

do { \
*(type *)(((WriteBufferObject *)data)->ptr) = v; \
type temp = v; \
memcpy(((WriteBufferObject *)data)->ptr, (const void *) &temp, sizeof(type)); \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same spacing inconsistency issue here.

#define _WRITE(data, type, v) \
do { \
*(type *)(((WriteBufferObject *)data)->ptr) = v; \
type temp = v; \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the usage of _WRITE(), I'm not 100% sure whether the temporary variable is needed, but it's probably safer when dealing with variables passed as a function parameter.

@glaubitz
Copy link

Besides two minor nitpicks with the formatting (spacing), the changes look good to me and I think it's the way to go to avoid unaligned access which can cause performance issues on other architectures besides the Bus error exception on SPARC.

Thanks for fixing this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unaligned memory access in _write_short_int

2 participants