https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127334
Bug ID: 127334
Summary: [x86_64] -fstack-clash-protection misses probes for
large outgoing aggregate arguments
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: 220255623 at seu dot edu.cn
CC: 220245569 at seu dot edu.cn, jianhao.xu at seu dot edu.cn
Target Milestone: ---
Created attachment 65562
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65562&action=edit
trigger.i
GCC emits no stack-clash probe for a large aggregate outgoing argument on
generic x86 targets. A single 8200-byte stack-pointer adjustment crosses two
4 KB probe intervals before the argument is copied.
Reproducer, no include directives:
struct Big { char data[8192]; };
extern struct Big g;
void callee(struct Big);
void caller(void) { callee(g); }
Command:
gcc -Os -fstack-clash-protection -S trigger.c -o trigger.s
Observed on GCC 17.0.0 20260531, x86_64-pc-linux-gnu:
caller:
.cfi_startproc
subq $8200, %rsp
leaq g(%rip), %rsi
movl $2048, %ecx
movq %rsp, %rdi
rep movsl
call callee@PLT
addq $8200, %rsp
ret
There is no probe between the old and new stack-pointer values. At -O2 the
copy is a memcpy call, but the preceding subq $8200, %rsp is still unprobed.
Expected: with -fstack-clash-protection, no allocation may skip a probe
interval. A local volatile char[8192] with the same flags emits:
subq $4096, %rsp
orb $0, (%rsp)
subq $3976, %rsp
The RTL pro_and_epilogue dump reports:
Stack clash no probe small stack adjustment in prologue.
Stack clash residual allocation in prologue.
The real allocation appears later as a REG_ARGS_SIZE stack adjustment, after
the backend prologue probing decision. The outgoing-argument path reaches
push_block in expr.cc, which calls anti_adjust_stack directly and has no
stack-clash probe.
ACCUMULATE_OUTGOING_ARGS in config/i386/i386.h has no
flag_stack_clash_protection clause. The existing -mstack-arg-probe guard in
i386-options.cc forces maccumulate-outgoing-args because the argument area
must be probed, but there is no equivalent guard for
-fstack-clash-protection.
This is not specific to -Os. Generic GCC 17 failed at -O0, -O1, -O2, -O3, and
-Os. GCC 15.2.0, GCC 16.1.0, and the 20260426/20260531 GCC 17 snapshots also
failed. -m32 -Os/-O2 -S showed the same issue in i386 code generation.
-mstack-arg-probe emits:
movl $8200, %eax
call ___chkstk_ms
subq %rax, %rsp
This demonstrates that probing outgoing argument space is already supported.
Compiler information:
Target: x86_64-pc-linux-gnu
Configured with: <redacted-source-root>/configure
--prefix=<redacted-install-prefix> --disable-bootstrap --disable-multilib
--disable-nls --enable-
languages=c,c++ --enable-default-pie --enable-cet --disable-werror
--enable-checking=release --with-system-zlib --with-pkgversion=<redacted-local-
package>
Thread model: posix
gcc version 17.0.0 20260531 (experimental)
The source snapshot is upstream master revision
f20bc4c2fe00928013c533e241b89ae3a6724ca1.
This is a hardening-coverage bug. I have not demonstrated a runtime exploit.