]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
LoongArch: XALLOCAVEC allocate too large space on stack
authormengqinggang <mengqinggang@loongson.cn>
Thu, 11 Dec 2025 06:23:57 +0000 (14:23 +0800)
committerLulu Cheng <chenglulu@loongson.cn>
Fri, 12 Dec 2025 07:56:47 +0000 (15:56 +0800)
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 <xry111@xry111.site>
Reviewed-by: Lulu Cheng <chenglulu@loongson.cn>
gcc/config/loongarch/loongarch.cc
gcc/testsuite/gcc.target/loongarch/la32/memcpy.c [new file with mode: 0644]

index 61e112952ae63a79cd34103afb91e7ee36f2e066..cc0523f2ab72fbb2cc8d6ee5d285ef21fd9683e7 100644 (file)
@@ -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 (file)
index 0000000..e0654d1
--- /dev/null
@@ -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);
+}