This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C PATCH] Don't accept awkward flexarr member initialization (PR c/64417)


This PR shows that the C FE accepts an invalid code, where
a flexible array member is being initialized with a string
constant, but the structure with the flexible array member
is in an array.  GNU extension that allows initialization
of a flexible array members is a little bit of a gray area,
since we allow it even in some cases where the struct with
the flexible array member is not a top-level object, e.g.
struct in an union.  But an array with entries of different
size Just Can't Be Right.  Hopefully no existing code relies
on this "feature" (glibc should be ok).

Note that in
struct S { int x; char y[]; };
struct S s[] = { { 1, { 'a', '\0' } } };
struct S s2[] = { { 1, "a" } };
we already reject 's', but not 's2'.  I think we should eventually
also reject e.g.
struct A { int a; char b[]; };
struct B { struct A a; int i; };
struct B b = { { 1, "abc" }, 2 };
because the structure 'a' is not at the end of struct B.

Bootstrapped/regtested on {ppc64,x86_64}-linux, ok for trunk?

2015-01-06  Marek Polacek  <polacek@redhat.com>

	PR c/64417
c/
	* c-typeck.c (process_init_element): Disallow initialization of
	a flexible array member with a string constant if the structure
	is in an array.
testsuite/
	* gcc.c-torture/compile/pr28865.c: Add dg-errors.
	* gcc.dg/pr64417.c: New test.

diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c
index 0db43cc..38ba9b8 100644
--- gcc/c/c-typeck.c
+++ gcc/c/c-typeck.c
@@ -8809,6 +8809,33 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
 	      break;
 	    }
 
+	  /* Error for initialization of a flexible array member with
+	     a string constant if the structure is in an array.  E.g.:
+	     struct S { int x; char y[]; };
+	     struct S s[] = { { 1, "foo" } };
+	     is invalid.  */
+	  if (string_flag
+	      && fieldcode == ARRAY_TYPE
+	      && constructor_depth > 1
+	      && TYPE_SIZE (fieldtype) == NULL_TREE
+	      && DECL_CHAIN (constructor_fields) == NULL_TREE)
+	    {
+	      bool in_array_p = false;
+	      for (struct constructor_stack *p = constructor_stack;
+		   p && p->type; p = p->next)
+		if (TREE_CODE (p->type) == ARRAY_TYPE)
+		  {
+		    in_array_p = true;
+		    break;
+		  }
+	      if (in_array_p)
+		{
+		  error_init (loc, "initialization of flexible array "
+			      "member in a nested context");
+		  break;
+		}
+	    }
+
 	  /* Accept a string constant to initialize a subarray.  */
 	  if (value.value != 0
 	      && fieldcode == ARRAY_TYPE
diff --git gcc/testsuite/gcc.c-torture/compile/pr28865.c gcc/testsuite/gcc.c-torture/compile/pr28865.c
index aa6ae07..ef0eba54 100644
--- gcc/testsuite/gcc.c-torture/compile/pr28865.c
+++ gcc/testsuite/gcc.c-torture/compile/pr28865.c
@@ -5,12 +5,12 @@ struct var_len
 };
 
 /* Note - strictly speaking this array declaration is illegal
-   since each element has a variable length.  GCC allows it
-   (for the moment) because it is used in existing code, such
-   as glibc.  */
+   since each element has a variable length.  We used to allow
+   this because it was used in existing code.
+   Since PR64417 we reject this code.  */
 static const struct var_len var_array[] = 
 {
-  { 1, "Long exposure noise reduction" },
-  { 2, "Shutter/AE lock buttons" },
-  { 3, "Mirror lockup" }
+  { 1, "Long exposure noise reduction" }, /* { dg-error "initialization of flexible array member" } */
+  { 2, "Shutter/AE lock buttons" }, /* { dg-error "initialization of flexible array member" } */
+  { 3, "Mirror lockup" } /* { dg-error "initialization of flexible array member" } */
 };
diff --git gcc/testsuite/gcc.dg/pr64417.c gcc/testsuite/gcc.dg/pr64417.c
index e69de29..15a336d 100644
--- gcc/testsuite/gcc.dg/pr64417.c
+++ gcc/testsuite/gcc.dg/pr64417.c
@@ -0,0 +1,16 @@
+/* PR c/64417 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct foo { int x; char y[]; };
+struct bar { struct foo f; };
+struct baz { struct bar b; };
+
+struct foo a1 = { 1, "abc" };
+struct foo a2 = { 1, { "abc" } };
+struct foo b1[] = { { 1, "abc" } }; /* { dg-error "initialization of flexible array member" } */
+struct foo b2[] = { { 1, { "abc" } } }; /* { dg-error "initialization of flexible array member" } */
+struct bar c1[] = { { { 1, "abc" } } }; /* { dg-error "initialization of flexible array member" } */
+struct bar c2[] = { { { 1, { "abc" } } } }; /* { dg-error "initialization of flexible array member" } */
+struct baz d1[] = { { { { 1, "abc" } } } }; /* { dg-error "initialization of flexible array member" } */
+struct baz d2[] = { { { { 1, { "abc" } } } } }; /* { dg-error "initialization of flexible array member" } */

	Marek


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]