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

            Bug ID: 69696
           Summary: incorrect initialization of block-scope flexible array
                    members
           Product: gcc
           Version: 6.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

As pointed in the following discussion
https://gcc.gnu.org/ml/gcc-patches/2016-02/msg00420.html, g++ allows local
structs with flexible array members to be initialized on definition but then
allocates the arrays in a way that overlaps other local variables, leading to
data corruption.  In C mode, GCC rejects initialization of such structs (this
was done to fix bug 28865).

G++ should either also reject initialiation of such structs, or it should do it
without this overlapping problem.  Note that bug 68489 is also related to this
problem, as is bug 69338.

The following test case shows that while structures containing flexible array
members and having static or thread storage duration are initialized correctly,
those having automatic storage duration are not. 

$ cat t.c && /build/gcc-trunk/gcc/xgcc -B /build/gcc-trunk/gcc -Wall -Wextra
-Wpedantic -xc++ t.c && ./a.out
enum { X = 12345678, Y = 87654321 };

struct A { int n, a []; };
struct A a0 = { 1, { 2, 3, 4 } };

void print (const int *i, struct A *a, const int *j)
{
    __builtin_printf ("\ni = %i\n"
                      "a = { %i, { %i, %i, %i }\n"
                      "j = %i\n",
                      *i, a->n, a->a[0], a->a[1], a->a[2],
                      *j);

    if (*i != X || *j != Y || a->a[0] != 2 || a->a[1] != 3 || a->a[2] != 4)
       __builtin_abort ();
 }

int main ()
{
    {
        static int i = X;
        static struct A a = { 1, { 2, 3, 4 } };
        static int j = Y;

        print (&i, &a, &j);
    }
    {
        __thread int i = X;
        __thread struct A a = { 1, { 2, 3, 4 } };
        __thread int j = Y;

        print (&i, &a, &j);
    }
    {
        int i = X;
        struct A a = { 1, { 2, 3, 4 } };
        int j = Y;

        print (&i, &a, &j);
    }
}
t.c:4:32: warning: initialization of a flexible array member [-Wpedantic]
 struct A a0 = { 1, { 2, 3, 4 } };
                                ^
t.c: In function ‘int main()’:
t.c:22:46: warning: initialization of a flexible array member [-Wpedantic]
         static struct A a = { 1, { 2, 3, 4 } };
                                              ^
t.c:28:22: warning: function-scope ‘i’ implicitly auto and declared ‘__thread’
         __thread int i = X;
                      ^
t.c:29:27: warning: function-scope ‘a’ implicitly auto and declared ‘__thread’
         __thread struct A a = { 1, { 2, 3, 4 } };
                           ^
t.c:29:48: warning: initialization of a flexible array member [-Wpedantic]
         __thread struct A a = { 1, { 2, 3, 4 } };
                                                ^
t.c:30:22: warning: function-scope ‘j’ implicitly auto and declared ‘__thread’
         __thread int j = Y;
                      ^
t.c:36:39: warning: initialization of a flexible array member [-Wpedantic]
         struct A a = { 1, { 2, 3, 4 } };
                                       ^

i = 12345678
a = { 1, { 2, 3, 4 }
j = 87654321

i = 12345678
a = { 1, { 2, 3, 4 }
j = 87654321

i = 4
a = { 1, { 2, 3, 4 }
j = 87654321
Aborted (core dumped)

Reply via email to