#344
Reject global and TLS initializers that store pointers at misaligned offsets
Work mostly by Opus 5.5.
I also put a more friendly write-up with a video introduction on https://mbrock.github.io/filnix/misaligned-initializers/ which may be of interest to someone.
A packed record (or an array of packed records/unions whose stride is not a multiple of 8) can put a pointer at a non-word offset in a global or thread-local initializer. Such a pointer has no shadow word of its own, and initializers are stored without the alignent checks that guard ordinary pointer loads and stores.
int anchor = 5;
struct __attribute__((packed)) P { char c; int *p; };
_Thread_local struct P t = { 1, &anchor }; /* or a plain global */On 0.686 this does two different bad things:
- Global:
computeConstantRelocationsasserts!(Offset % WordSize)and clang aborts (exit 134) instead of diagnosing the program. - Thread-local: the getter stores the initializer with
storeValueRecurseAfterCheck, which writes the capability ataux + 1, across two shadow words, under a falsealign 8. Shadow word 0 then holds the capability shifted by a byte — non-null, but not a capability. A later ordinary aligned pointer load of word 0 (where the initializer never stored a pointer) reads that garbage as a capability and the program segfaults with no Fil-C diagnostic.
This patch makes both cases a compile error:
error: Fil-C cannot initialize 't': a pointer in its initializer is not word-aligned