Skip to content

Commit

Permalink
Disable UBSAN for alignment-sensitive functions when !CAREFUL_ALIGNMENT
Browse files Browse the repository at this point in the history
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: #427
  • Loading branch information
thesamesam committed Jan 9, 2023
1 parent 90df93e commit b0a8dc2
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 6 deletions.
31 changes: 27 additions & 4 deletions byteorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions io.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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];
Expand Down

0 comments on commit b0a8dc2

Please sign in to comment.