From d520c8054f47b5257d1451eb678dfff7fa81fd01 Mon Sep 17 00:00:00 2001 From: Sam James Date: Mon, 9 Jan 2023 06:30:28 +0000 Subject: [PATCH] Disable UBSAN for alignment-sensitive functions when !CAREFUL_ALIGNMENT rsync sets CAREFUL_ALIGNMENT for architectures which do not support unaligned access. Disable UBSAN for functions which may use unaligned accesses when CAREFUL_ALIGNMENT is set. Bug: https://github.com/WayneD/rsync/issues/427 Signed-off-by: Sam James --- byteorder.h | 31 +++++++++++++++++++++++++++++++ io.c | 10 ++++++++++ 2 files changed, 41 insertions(+) diff --git a/byteorder.h b/byteorder.h index 059cc7086..855e8fe14 100644 --- a/byteorder.h +++ b/byteorder.h @@ -68,10 +68,26 @@ SIVAL64(char *buf, int pos, int64 val) #else /* !CAREFUL_ALIGNMENT */ +/* We don't want false positives about alignment from UBSAN, see: + https://github.com/WayneD/rsync/issues/427#issuecomment-1375132291 +*/ + +/* From https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html */ +#ifndef GCC_VERSION +#define GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) +#endif + /* This handles things for architectures like the 386 that can handle alignment errors. * WARNING: This section is dependent on the length of an int32 (and thus a uint32) * being correct (4 bytes)! Set CAREFUL_ALIGNMENT if it is not. */ +#ifdef __clang__ +__attribute__((no_sanitize("undefined"))) +#elif GCC_VERSION >= 409 +__attribute__((no_sanitize_undefined)) +#endif static inline uint32 IVALu(const uchar *buf, int pos) { @@ -83,6 +99,11 @@ IVALu(const uchar *buf, int pos) return *u.num; } +#ifdef __clang__ +__attribute__((no_sanitize("undefined"))) +#elif GCC_VERSION >= 409 +__attribute__((no_sanitize_undefined)) +#endif static inline void SIVALu(uchar *buf, int pos, uint32 val) { @@ -94,6 +115,11 @@ SIVALu(uchar *buf, int pos, uint32 val) *u.num = val; } +#ifdef __clang__ +__attribute__((no_sanitize("undefined"))) +#elif GCC_VERSION >= 409 +__attribute__((no_sanitize_undefined)) +#endif static inline int64 IVAL64(const char *buf, int pos) { @@ -105,6 +131,11 @@ IVAL64(const char *buf, int pos) return *u.num; } +#ifdef __clang__ +__attribute__((no_sanitize("undefined"))) +#elif GCC_VERSION >= 409 +__attribute__((no_sanitize_undefined)) +#endif static inline void SIVAL64(char *buf, int pos, int64 val) { diff --git a/io.c b/io.c index a99ac0ec5..2ead72d47 100644 --- a/io.c +++ b/io.c @@ -1791,6 +1791,11 @@ uint32 read_uint(int f) return IVAL(b, 0); } +#ifdef __clang__ +__attribute__((no_sanitize("undefined"))) +#elif GCC_VERSION >= 409 +__attribute__((no_sanitize_undefined)) +#endif int32 read_varint(int f) { union { @@ -1823,6 +1828,11 @@ int32 read_varint(int f) return u.x; } +#ifdef __clang__ +__attribute__((no_sanitize("undefined"))) +#elif GCC_VERSION >= 409 +__attribute__((no_sanitize_undefined)) +#endif int64 read_varlong(int f, uchar min_bytes) { union {