On Sun, Jul 26, 2026 at 6:47 PM Keith Packard <[email protected]> wrote: > > Risc-V ILP32E ABI requires only a 4-byte stack alignment, rather than 16 > as used on all other Risc-V ABIs. > > That means any pointers to data on the stack are only going to be 4-byte > aligned, independent of the underlying representation. > > When ubsan generates pointer alignment checks, it uses the basic type > alignment value (found in mode_base_align), and on Risc-V, those are > set to the size of the type, at least for types <= 16 bytes. > > This sample code shows the issue: > > int > bar(unsigned long long *offsetp) > { > *offsetp += 8; > return 0; > } > > Compiled for ilp32e: > > $ cc1 -march=rv32e -mabi=ilp32e -O2 -fsanitize=undefined > riscv-align-bug.c > > The compiler emits: > > bar: > addi sp,sp,-16 > sw ra,12(sp) > mv a1,a0 > beq a0,zero,.L2 > andi a5,a0,7 <- Checking lower 3 bits for 8-byte > alignment > bne a5,zero,.L2 > .L3: > ... > > Fixing this is relatively straightforward; simply relax the alignment > constrants in the ubsan code to no more than STACK_BOUNDARY bits.
> > I'm unsure whether to fix the ubsan code or to adjust the alignment > requirements in riscv-modes.def: > > ADJUST_ALIGNMENT (DI, riscv_abi == ABI_ILP32E ? UNITS_PER_WORD : > mode_base_align[E_DImode]); > ADJUST_ALIGNMENT (TI, riscv_abi == ABI_ILP32E ? UNITS_PER_WORD : > mode_base_align[E_TImode]); I doubt this is correct either. What does the ILP32E abi say? Does it say `long long` is 4 byte aligned? from https://docs.riscv.org/reference/abi/v1.0/riscv-cc-procedure-calling-convention.html : RV32E is not a ratified base ISA and so we cannot guarantee the stability of ILP32E, in contrast with the rest of this document. This documents the current implementation in GCC as of the time of writing, but may be subject to change. So there is no ABI document it seems. > ... > > Guidance here would be appreciated. > > Signed-off-by: Keith Packard <[email protected]> > --- > gcc/ubsan.cc | 7 +++++++ > 1 file changed, 7 insertions(+) > > diff --git a/gcc/ubsan.cc b/gcc/ubsan.cc > index 79a863b46ce..27906dd1704 100644 > --- a/gcc/ubsan.cc > +++ b/gcc/ubsan.cc > @@ -1450,6 +1450,13 @@ instrument_mem_ref (tree mem, tree base, > gimple_stmt_iterator *iter, > align = min_align_of_type (TREE_TYPE (base)); > if (align <= 1) > align = 0; > + /* > + * Any pointer might reference data on the stack, which is > + * only constrained to STACK_BOUNDARY. If that is less strict > + * than the type alignment, relax our checks to that value > + */ > + if (align > STACK_BOUNDARY / BITS_PER_UNIT) > + align = STACK_BOUNDARY / BITS_PER_UNIT; This is definitely not correct and will break other targets where the stack is realigned for that purpose. The stack should be realigned if there is a mode that requires a higher alignment. > } > if (align == 0) > { > -- > 2.53.0 >
