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

--- Comment #8 from Akihiko Odaki <akihiko.odaki at daynix dot com> ---
(In reply to Jakub Jelinek from comment #7)
> GCC actually doesn't diagnose on mere pointer assignment, but what triggers
> the alignment check is
> &entry->offset
> even when the code later on just takes its address, entry must be
> sufficiently aligned, otherwise entry->offset is invalid.
> Under standard C rules, already forming the pointer would be UB, so
> somewhere in the caller when you prepare what to pass to the f function.
> 
> If you want something that will still be invalid C,
> but will not trigger UBSAN errors, then e.g.
> unsigned long long h(struct dir_entry *entry)
> {
>     return get_unaligned((unsigned long long *) (((char *) entry) + offsetof
> (struct dir_entry, offset)));
> }
> will do.

It would certainly workaround the issue, but it's only dirtier and brings no
benefit except suppressed UBSan errors. Why not allow
get_unaligned(&entry->offset) when UBSan does not complain about that hack?

> If you want something that will be valid even in C, don't pass struct
> dir_entry *entry
> argument, but void *entry instead, and use e.g.
> __get_unaligned_t(__typeof(((struct dir_entry *)0)->offset), ((char
> *)entry)+offsetof(struct dir_entry, offset)))
> You can surely hide that all under some macro.

The definition still involves UB for ((struct dir_entry *)0)->offset. Perhaps
__typeof() may be considered as an exception, but what if offsetof() is defined
as follows?

#define offsetof(T, x) ((uintptr_t)&(((T *)0)->x))

GCC does provide __builtin_offsetof(), but I think definitions of offsetof()
like this are still prevalent, and expected to work although it's UB. If GCC
tolerates this kind of trick, why not tolerate get_unaligned(&entry->offset)?

Reply via email to