https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93031

--- Comment #3 from Pascal Cuoq <pascal_cuoq at hotmail dot com> ---
@amonakov

The two blog posts below exist themselves, and describe tools that exist,
because software that makes misaligned access exists, although it seems to
be a “examples too numerous to list” situation (or, more optimistically,
perhaps one where the source code is fixed upstream as problems are found).

https://blogs.oracle.com/d/on-misaligned-memory-accesses
https://blog.quarkslab.com/unaligned-accesses-in-cc-what-why-and-solutions-to-do-it-properly.html

(In the end it's the binary executable that doesn't work, and both
posts deal with that aspect at some point, but these executables were
not written in SPARC or respectively ARM assembly. If they had been,
they would have been written to work. Instead, they were written in a
higher-level language that was translated to SPARC/ARM assembly,
presumably C.)


For a specific example, fifteen minutes of looking around knowing what
one is looking for turns up the LZO implementation from
http://www.oberhumer.com/opensource/lzo/ . In the latest
version to date, 2.10:

#if (LZO_ARCH_ALPHA)
#  define LZO_OPT_AVOID_UINT_INDEX          1
#elif (LZO_ARCH_AMD64)
#  define LZO_OPT_AVOID_INT_INDEX           1
#  define LZO_OPT_AVOID_UINT_INDEX          1
#  ifndef LZO_OPT_UNALIGNED16
#  define LZO_OPT_UNALIGNED16               1
#  endif
#  ifndef LZO_OPT_UNALIGNED32
#  define LZO_OPT_UNALIGNED32               1
#  endif
#  ifndef LZO_OPT_UNALIGNED64
#  define LZO_OPT_UNALIGNED64               1
#  endif
#elif (LZO_ARCH_ARM)
#  if defined(__ARM_FEATURE_UNALIGNED)
#   if ((__ARM_FEATURE_UNALIGNED)+0)
#    ifndef LZO_OPT_UNALIGNED16
#    define LZO_OPT_UNALIGNED16             1
#    endif
#    ifndef LZO_OPT_UNALIGNED32
#    define LZO_OPT_UNALIGNED32             1
#    endif
#   endif
#  elif 1 && (LZO_ARCH_ARM_THUMB2)

...

#if (LZO_OPT_UNALIGNED32)
LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4)
#define LZO_MEMOPS_COPY4(dd,ss) \
    * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p)
(const lzo_memops_TU0p) (ss)
#elif defined(lzo_memops_tcheck__)
#define LZO_MEMOPS_COPY4(dd,ss) \
    LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU4,4,1)) { \
        * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p)
(const lzo_memops_TU0p) (ss); \
    } else { LZO_MEMOPS_MOVE4(dd,ss); } LZO_BLOCK_END
#else
#define LZO_MEMOPS_COPY4(dd,ss) LZO_MEMOPS_MOVE4(dd,ss)
#endif

...

It is good news that this particular piece of software is already
designed to work on compilation platforms where misaligned accesses
are forbidden. But if anyone compiles it today with GCC for amd64 or
for “__ARM_FEATURE_UNALIGNED”, they are at risk of an optimization
firing and making the library not work as intended, perhaps in obscure
cases with safety or security implications.

I will state, despite the risk of tedious repetition, that the LZO
implementation invokes Undefined Behavior. I know it, Oberhumer
clearly knows it, and anyone who has read this far knows it. However
the perception of some GCC users (not me!) may be that GCC is once
again changing the rules and taking an Undefined Behavior that would
obviously never cause an actual demon to come out of one's nose, such
as a source file missing a final newline, and changing it into
one that does.

Reply via email to