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

            Bug ID: 128369
           Summary: no_sanitize_address on a prior declaration is lost
                    when the definition adds no_sanitize_undefined
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: sanitizer
          Assignee: unassigned at gcc dot gnu.org
          Reporter: 220245569 at seu dot edu.cn
                CC: 220255623 at seu dot edu.cn, dodji at gcc dot gnu.org,
                    dvyukov at gcc dot gnu.org, jakub at gcc dot gnu.org,
                    jianhao.xu at seu dot edu.cn, kcc at gcc dot gnu.org
  Target Milestone: ---
            Target: *-*-*

Reproducer
----------
$ cat trigger.c
int g_arr[4];
int g_sink;

void __attribute__((no_sanitize_address)) probe (void);
void __attribute__((no_sanitize_undefined)) probe (void)
{
  g_arr[4] = 1;                 /* must not be ASan-instrumented */
  g_sink = g_sink + 0x7fffffff; /* must not be UBSan-instrumented */
}

void __attribute__((no_sanitize_address)) control (void);
void control (void)
{
  g_arr[4] = 2;                 /* single attribute: correctly not
ASan-instrumented */
}

Compile flag: x86_64-linux-gnu-gcc -O1 -fsanitize=address,undefined -S
trigger.c

probe:                                    # no_sanitize_address (decl) +
no_sanitize_undefined (def)
        movl    $g_arr+16, %eax
        shrq    $3, %rax
        movzbl  2147450880(%rax), %eax           # ASan shadow check: should
not be here
        ...
        call    __asan_report_store4
control:                                  # no_sanitize_address on the decl
only
        call    __ubsan_handle_out_of_bounds     # UBSan still on (expected),
no ASan check
        movl    $2, g_arr+16(%rip)

Root cause
----------
The attribute handler folds sanitizer bits into one "no_sanitize" node via
add_no_sanitize_value (gcc/c-family/c-attribs.cc:1457-1476), but only for
attributes on the same declaration.  For a redeclaration the new decl gets
its own node and merge_decls (gcc/c/c-decl.cc:2812, also cp/decl.cc:2716)
calls merge_attributes (gcc/attribs.cc:1733), which keeps both nodes
because their values differ.  sanitize_flags_p (gcc/asan.h:262) uses
lookup_attribute ("no_sanitize", ...) and reads only the first node, so the
SANITIZE_ADDRESS bit of the earlier declaration is ignored.  GCC trunk
(Compiler Explorer, 2026-11-01) still instruments probe().

Suggested Fix
-------------
When merging declarations, OR the values of all "no_sanitize" nodes into a
single node (e.g. in merge_attributes / diag_attr_exclusions path), or make
sanitize_flags_p iterate over every "no_sanitize" node.

Reply via email to