https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128390

            Bug ID: 128390
           Summary: -fcf-protection=none does not clear a preceding
                    -fcf-protection=check (__CET__ stays defined, CET EH
                    return still used)
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: driver
          Assignee: unassigned at gcc dot gnu.org
          Reporter: 220245569 at seu dot edu.cn
                CC: 220255623 at seu dot edu.cn, jianhao.xu at seu dot edu.cn
  Target Milestone: ---
            Target: x86_64-*-* i?86-*-*

Reproducer
----------
$ cat trigger.c
#ifdef __CET__
int cet_macro = __CET__;
#endif

void
eh_ret (long off, void *handler)
{
  __builtin_eh_return (off, handler);
}

Compile flag: x86_64-linux-gnu-gcc -O2 -fcf-protection=check
-fcf-protection=none -S trigger.c

# __CET__ after each option sequence (-dM -E)
-fcf-protection=none                                   => (undefined)
-fcf-protection=full -fcf-protection=none              => (undefined)
-fcf-protection=check -fcf-protection=none             => #define __CET__ 8    
# expected undefined
-fcf-protection=check -fcf-protection=none -fcf-protection=branch => #define
__CET__ 9

# eh_ret epilogue, -fcf-protection=check -fcf-protection=none
        leaq    16(%rsp,%rcx), %rsp
        popq    %rcx                 # CET-style EH return still selected
        jmp     *%rcx
# eh_ret epilogue, -fcf-protection=none
        leaq    16(%rsp,%rcx), %rsp
        ret

Root cause
----------
fcf-protection= is an EnumSet option.  In gcc/common.opt (2131-2146)
'none' (CF_NONE == 0) is in Set(1) with 'full', while 'check' (CF_CHECK)
is alone in Set(4).  decode_cmdline_option only clears the bits of the
selected set (opts-common.cc:866-874), so =none clears CF_BRANCH|CF_RETURN
but keeps CF_CHECK.  ix86_option_override_internal then adds CF_SET
(i386-options.cc:3144-3151), ix86_target_macros defines __CET__=8
(i386-c.cc:976-977) and the EH-return epilogue tests flag_cf_protection
(i386.cc:10765).  The manual says "The value none turns off
instrumentation" and documents "-fcf-protection=none" as the way to
override a previous option.  Distinct from the __CET__ value under
-fcf-protection=check alone.

Suggested Fix
-------------
Make =none reset every set, e.g. handle OPT_fcf_protection_ with value
CF_NONE specially (flag_cf_protection = CF_NONE), or give 'check' the same
Set as 'none' so that the mask covers CF_CHECK.

Reply via email to