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

            Bug ID: 110292
           Summary: undefined value due to strict aliasing without warning
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: yann at droneaud dot fr
  Target Milestone: ---

The following code (reduced with some help from cvise) doesn't trigger any
warning from GCC 13+

    $ cat test.c
    #include <stdint.h>

    struct a {
      uint8_t b:6;
    };

    struct c {
      uint64_t d:6;
    };

    void e(uint64_t *f, uint64_t *g) {
      struct c *h = (struct c *)f;
      struct a i[8] = { [7] = { h -> d } };
      __builtin___memcpy_chk (g, i, sizeof(i),
         __builtin_object_size (g, 0));
    }

    int main(void) {
      uint64_t j = 0;
      uint64_t k;
      e(&j, &k);
      if (k)
        __builtin_trap();

      return 0;
    }

But compiled under Fedora 39 (Rawhide, gcc 13.1.1-2, x86_64), it aborts,
because j location on the stack is not set to 0 before its address is being
passed to e() ... 

    $ gcc -Wall -Wextra -O2 test.c -o test
    $ ./test
    Aborted (core dumped)

Even if it doesn't abort (because the stack is cleared), there's a problem and
valgrind reports:

    $ gcc -Wall -Wextra -O2 -g3 test.c -o test
    $ valgrind --track-origins=yes ./test 
    ==63110== Memcheck, a memory error detector
    ==63110== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
    ==63110== Using Valgrind-3.21.0 and LibVEX; rerun with -h for copyright
info
    ==63110== Command: ./test
    ==63110== 
    ==63110== Conditional jump or move depends on uninitialised value(s)
    ==63110==    at 0x401047: main (test.c:22)
    ==63110==  Uninitialised value was created by a stack allocation
    ==63110==    at 0x401030: main (test.c:18)
   ...

And, as one could see, line 18 doesn't match any of the variables that are
allocated.

Below, the assembly compiled by GCC:
    $ gcc -Wall -Wextra -O2 -g3 test.c -S
    $ cat test.s
    e:
        movzbl  (%rdi), %eax
        andl    $63, %eax
        salq    $56, %rax
        movq    %rax, (%rsi)
        ret
    main:
        subq    $16, %rsp
        leaq    8(%rsp), %rsi
        movq    %rsp, %rdi
        call    e
        cmpq    $0, 8(%rsp)
        jne     .L5
        xorl    %eax, %eax
        addq    $16, %rsp
        ret
    .L5:
        ud2

Code available at https://godbolt.org/z/b8sn314K9

Is it an aliasing issue in the code and GCC doesn't reports a warning ? Or
worse ?

Reply via email to