https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114217
Bug ID: 114217 Summary: -fsanitize=alignment false positive with intended unaligned struct member access Product: gcc Version: 13.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: sanitizer Assignee: unassigned at gcc dot gnu.org Reporter: akihiko.odaki at daynix dot com CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org, jakub at gcc dot gnu.org, kcc at gcc dot gnu.org Target Milestone: --- -fsanitize=alignment generates a false positive error for an intended unaligned struct member access. The intention of unaligned struct member access is expressed with __builtin_memcpy() as done by QEMU or packed struct access as done by Linux. GCC translates such a construct to code to access memory unaligned for architectures like rv64gc as intended but also emits code to enforce the alignment. The relevant code of QEMU is at: https://gitlab.com/qemu-project/qemu/-/blob/v8.2.1/include/qemu/bswap.h?ref_type=tags The relevant code of Linux is at: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/asm-generic/unaligned.h?h=v6.7 FYI, this issue is reproducible also with clang 17.0.1, and I'm going to open an issue for it, too. To reproduce the issue, compile the code shown below with -O2 -fsanitize=alignment for rv64gc: #include <stdint.h> typedef uint64_t u64; /* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/compiler_attributes.h?h=v6.7 */ /* * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-packed-type-attribute * clang: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-packed-variable-attribute */ #define __packed __attribute__((__packed__)) /* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/asm-generic/unaligned.h?h=v6.7 */ #define __get_unaligned_t(type, ptr) ({ \ const struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \ __pptr->x; \ }) #define __put_unaligned_t(type, val, ptr) do { \ struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr); \ __pptr->x = (val); \ } while (0) #define get_unaligned(ptr) __get_unaligned_t(typeof(*(ptr)), (ptr)) #define put_unaligned(val, ptr) __put_unaligned_t(typeof(*(ptr)), (val), (ptr)) /* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/btrfs/inode.c?h=v6.7 */ struct dir_entry { u64 ino; u64 offset; unsigned type; int name_len; }; /* * This function is intended to perform an unaligned access. * GCC emits code for an unaligned operation as intended, * but also emits code to assert alignment. */ u64 f(struct dir_entry *entry) { return get_unaligned(&entry->offset); } /* * This function is intended to perform an aligned access. * GCC emits code for an aligned operation, * and emits code to assert alignment. */ u64 g(struct dir_entry *entry) { return entry->offset; }