Skip to content

Commit 0c18d91

Browse files
authored
Fix unaligned memory access in librt internal helper function _write_short (#20474)
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).
1 parent 9dc9fc3 commit 0c18d91

1 file changed

Lines changed: 4 additions & 2 deletions

File tree

mypyc/lib-rt/librt_internal.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#define PY_SSIZE_T_CLEAN
44
#include <Python.h>
55
#include <stdint.h>
6+
#include <string.h>
67
#include "CPy.h"
78
#define LIBRT_INTERNAL_MODULE
89
#include "librt_internal.h"
@@ -39,13 +40,14 @@
3940

4041
#define _READ(result, data, type) \
4142
do { \
42-
*(result) = *(type *)(((ReadBufferObject *)data)->ptr); \
43+
memcpy((void *) result, ((ReadBufferObject *)data)->ptr, sizeof(type)); \
4344
((ReadBufferObject *)data)->ptr += sizeof(type); \
4445
} while (0)
4546

4647
#define _WRITE(data, type, v) \
4748
do { \
48-
*(type *)(((WriteBufferObject *)data)->ptr) = v; \
49+
type temp = v; \
50+
memcpy(((WriteBufferObject *)data)->ptr, (const void *) &temp, sizeof(type)); \
4951
((WriteBufferObject *)data)->ptr += sizeof(type); \
5052
} while (0)
5153

0 commit comments

Comments
 (0)