]> git.ipfire.org Git - thirdparty/rsync.git/commitdiff
Disable UBSAN for alignment-sensitive functions when !CAREFUL_ALIGNMENT
authorSam James <sam@gentoo.org>
Mon, 9 Jan 2023 06:30:28 +0000 (06:30 +0000)
committerAndrew Tridgell <andrew@tridgell.net>
Mon, 8 Jun 2026 10:54:57 +0000 (20:54 +1000)
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 <sam@gentoo.org>
(cherry picked from commit 11c1e934e8ac4a6c44fbd3d7bb171c04d928bb40)

byteorder.h
io.c

index 059cc70864953b564f24b7332343ab230fc28bcb..855e8fe1414cd40e477af0f3131674d7f5aa3912 100644 (file)
@@ -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 0b96c27095650369cc01d9dd064b94d58d09b8ea..8d240e441d54ae4d68325404f251a9dc9abb4c5d 100644 (file)
--- a/io.c
+++ b/io.c
@@ -1813,6 +1813,13 @@ uint32 read_uint(int f)
        return IVAL(b, 0);
 }
 
+#ifndef CAREFUL_ALIGNMENT
+#ifdef __clang__
+__attribute__((no_sanitize("undefined")))
+#elif GCC_VERSION >= 409
+__attribute__((no_sanitize_undefined))
+#endif
+#endif
 int32 read_varint(int f)
 {
        union {
@@ -1845,6 +1852,13 @@ int32 read_varint(int f)
        return u.x;
 }
 
+#ifndef CAREFUL_ALIGNMENT
+#ifdef __clang__
+__attribute__((no_sanitize("undefined")))
+#elif GCC_VERSION >= 409
+__attribute__((no_sanitize_undefined))
+#endif
+#endif
 int64 read_varlong(int f, uchar min_bytes)
 {
        union {