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.

Reply via email to