https://gcc.gnu.org/g:22b8e0c32aef7c9af71c62552beaca3dcdf12591
commit r16-6057-g22b8e0c32aef7c9af71c62552beaca3dcdf12591 Author: mengqinggang <[email protected]> Date: Thu Dec 11 14:23:57 2025 +0800 LoongArch: XALLOCAVEC allocate too large space on stack Compare (length > la_max_inline_memcpy_size) and (length <= align * LARCH_MAX_MOVE_OPS_STRAIGHT) is signed. But loongarch_block_move_straight() -> XALLOCAVEC() -> alloca() allocate space as unsigned value. It may result in segment fault if length > 0x7fffffff. gcc/ChangeLog: * config/loongarch/loongarch.cc (loongarch_block_move_loop): Change length, align to unsigned. (loongarch_expand_block_move): Ditto. gcc/testsuite/ChangeLog: * gcc.target/loongarch/la32/memcpy.c: New test. Reviewed-by: Xi Ruoyao <[email protected]> Reviewed-by: Lulu Cheng <[email protected]> Diff: --- gcc/config/loongarch/loongarch.cc | 10 +++++----- gcc/testsuite/gcc.target/loongarch/la32/memcpy.c | 10 ++++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 61e112952ae6..cc0523f2ab72 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -6195,8 +6195,8 @@ loongarch_adjust_block_mem (rtx mem, HOST_WIDE_INT length, rtx *loop_reg, the memory regions do not overlap. */ static void -loongarch_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length, - HOST_WIDE_INT align) +loongarch_block_move_loop (rtx dest, rtx src, unsigned HOST_WIDE_INT length, + unsigned HOST_WIDE_INT align) { rtx_code_label *label; rtx src_reg, dest_reg, final_src, test; @@ -6252,11 +6252,11 @@ loongarch_expand_block_move (rtx dest, rtx src, rtx r_length, rtx r_align) if (!CONST_INT_P (r_length)) return false; - HOST_WIDE_INT length = INTVAL (r_length); - if (length > la_max_inline_memcpy_size) + unsigned HOST_WIDE_INT length = UINTVAL (r_length); + if (length > (unsigned HOST_WIDE_INT) la_max_inline_memcpy_size) return false; - HOST_WIDE_INT align = INTVAL (r_align); + unsigned HOST_WIDE_INT align = UINTVAL (r_align); if (!TARGET_STRICT_ALIGN || align > LARCH_MAX_MOVE_PER_INSN) align = LARCH_MAX_MOVE_PER_INSN; diff --git a/gcc/testsuite/gcc.target/loongarch/la32/memcpy.c b/gcc/testsuite/gcc.target/loongarch/la32/memcpy.c new file mode 100644 index 000000000000..e0654d1ba7e4 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/la32/memcpy.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wno-stringop-overflow" } */ + +extern void *memcpy (const void *, const void *, unsigned int); + +void +test_memcpy (const void *p, const void *q) +{ + memcpy (p, q, 0x80000000); +}
