diff --git a/byteorder.h b/byteorder.h index 059cc708..ece3999b 100644 --- a/byteorder.h +++ b/byteorder.h @@ -68,11 +68,34 @@ 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 + +#ifndef RSYNC_NO_UBSAN_ATTR +# ifdef CAREFUL_ALIGNMENT +# ifdef __clang__ +# define RSYNC_NO_UBSAN_ATTR __attribute__((no_sanitize("undefined"))) +# elif GCC_VERSION >= 409 +# define RSYNC_NO_UBSAN_ATTR __attribute__((no_sanitize_undefined)) +# endif +# else +# define RSYNC_NO_UBSAN_ATTR +# endif +#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. */ -static inline uint32 +RSYNC_NO_UBSAN_ATTR static inline uint32 IVALu(const uchar *buf, int pos) { union { @@ -83,7 +106,7 @@ IVALu(const uchar *buf, int pos) return *u.num; } -static inline void +RSYNC_NO_UBSAN_ATTR static inline void SIVALu(uchar *buf, int pos, uint32 val) { union { @@ -94,7 +117,7 @@ SIVALu(uchar *buf, int pos, uint32 val) *u.num = val; } -static inline int64 +RSYNC_NO_UBSAN_ATTR static inline int64 IVAL64(const char *buf, int pos) { union { @@ -105,7 +128,7 @@ IVAL64(const char *buf, int pos) return *u.num; } -static inline void +RSYNC_NO_UBSAN_ATTR static inline void SIVAL64(char *buf, int pos, int64 val) { union { diff --git a/io.c b/io.c index a99ac0ec..bf595bad 100644 --- a/io.c +++ b/io.c @@ -1791,7 +1791,7 @@ uint32 read_uint(int f) return IVAL(b, 0); } -int32 read_varint(int f) +RSYNC_NO_UBSAN_ATTR int32 read_varint(int f) { union { char b[5]; @@ -1823,7 +1823,7 @@ int32 read_varint(int f) return u.x; } -int64 read_varlong(int f, uchar min_bytes) +RSYNC_NO_UBSAN_ATTR int64 read_varlong(int f, uchar min_bytes) { union { char b[9];