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

            Bug ID: 128274
           Summary: [16/17 Regression] &p->payload on counted_by FAM omits
                    .ACCESS_WITH_SIZE in build_unary_op
           Product: gcc
           Version: 16.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          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: *-*-*

Summary
-------
In GCC 16/17, taking the address of a flexible array member annotated with
`__attribute__((counted_by(count)))` via `&p->payload` omits the
`.ACCESS_WITH_SIZE` wrapper, causing
`__builtin_dynamic_object_size(&p->payload, 0)`
to return `-1` (unknown) and `_FORTIFY_SOURCE=3` `__memcpy_chk` to fold to an
unchecked `memcpy`.

When GCC 16 refactored `.ACCESS_WITH_SIZE` generation out of
`build_component_ref`
into callers (`c_decay_conversion` for array-to-pointer decay `p->payload`), it
missed the `ADDR_EXPR` case in `build_unary_op`
(`gcc/c/c-typeck.cc:6219-6339`).
As a result, while `p->payload` emits `.ACCESS_WITH_SIZE` and evaluates
`__builtin_dynamic_object_size` to `p->count`, `&p->payload` emits a raw
`ADDR_EXPR <COMPONENT_REF>` and loses its dynamic bound.

Reproducer
----------
$ cat trigger.c
#include <stddef.h>

struct packet {
    size_t count;
    char payload[] __attribute__((counted_by(count)));
};

size_t bdos_decay(struct packet *p) {
    return __builtin_dynamic_object_size(p->payload, 0);
}

size_t bdos_addr(struct packet *p) {
    return __builtin_dynamic_object_size(&p->payload, 0);
}

void copy_addr(struct packet *p, const void *src, size_t len) {
    __builtin___memcpy_chk(
        &p->payload, src, len, __builtin_dynamic_object_size(&p->payload, 0));
}

Compile flag: gcc -O2 -S trigger.c

$ cat trigger.s
bdos_decay:
        movq    (%rdi), %rax            # returns p->count
        ret

bdos_addr:
        movq    $-1, %rax               # BUG: returns -1 (unknown)!
        ret

copy_addr:
        addq    $8, %rdi
        jmp     memcpy                  # BUG: __memcpy_chk folded to unchecked
memcpy!

Suggested Fix
-------------
In `build_unary_op` (`gcc/c/c-typeck.cc:6335`, `case ADDR_EXPR:`), call
`c_build_fun_call_access_with_size` when the operand is a `COMPONENT_REF`
referencing a `counted_by` flexible array member.

Reply via email to