]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Avoid infinite loop with duplicate anonymous union fields (PR c/86690).
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 3 Aug 2018 15:25:35 +0000 (15:25 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 3 Aug 2018 15:25:35 +0000 (15:25 +0000)
If a struct contains an anonymous union and both have a field with the
same name, detect_field_duplicates_hash() will replace one of them
with NULL.  If compilation doesn't stop immediately, it may later call
lookup_field() on the union, which falsely assumes the union's
LANG_SPECIFIC array is sorted, and may loop indefinitely because of
this.

2018-08-03  Bogdan Harjoc  <harjoc@gmail.com>

PR c/86690
gcc/c:
* c-typeck.c (lookup_field): Do not use TYPE_LANG_SPECIFIC after
errors.

gcc/testsuite:
* gcc.dg/union-duplicate-field.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@263294 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/union-duplicate-field.c [new file with mode: 0644]

index 6e682cdb140e27631303380f9be66257b27fcb95..40e56f3aaaa22bdf7046bd83ec84e4f302ddc36c 100644 (file)
@@ -1,3 +1,9 @@
+2018-08-03  Bogdan Harjoc  <harjoc@gmail.com>
+
+       PR c/86690
+       * c-typeck.c (lookup_field): Do not use TYPE_LANG_SPECIFIC after
+       errors.
+
 2018-08-01  Martin Sebor  <msebor@redhat.com>
 
        PR tree-optimization/86650
index f6a326c8152cde22adb092bc7f47a1064f798d20..2e9338e3458b4ccfc07fb5f9a21795321bf2167d 100644 (file)
@@ -2207,9 +2207,14 @@ lookup_field (tree type, tree component)
   /* If TYPE_LANG_SPECIFIC is set, then it is a sorted array of pointers
      to the field elements.  Use a binary search on this array to quickly
      find the element.  Otherwise, do a linear search.  TYPE_LANG_SPECIFIC
-     will always be set for structures which have many elements.  */
+     will always be set for structures which have many elements.
 
-  if (TYPE_LANG_SPECIFIC (type) && TYPE_LANG_SPECIFIC (type)->s)
+     Duplicate field checking replaces duplicates with NULL_TREE so
+     TYPE_LANG_SPECIFIC arrays are potentially no longer sorted.  In that
+     case just iterate using DECL_CHAIN.  */
+
+  if (TYPE_LANG_SPECIFIC (type) && TYPE_LANG_SPECIFIC (type)->s
+      && !seen_error ())
     {
       int bot, top, half;
       tree *field_array = &TYPE_LANG_SPECIFIC (type)->s->elts[0];
index 966c13b33cfdf9a32bb71b998d6bcf26b26f4e13..ba0c4c6ef5dff572cda798d53a2ec36b8a27a88a 100644 (file)
@@ -1,3 +1,8 @@
+2018-08-03  Bogdan Harjoc  <harjoc@gmail.com>
+
+       PR c/86690
+       * gcc.dg/union-duplicate-field.c: New test.
+
 2018-08-03  Jason Merrill  <jason@redhat.com>
 
        PR c++/86706
diff --git a/gcc/testsuite/gcc.dg/union-duplicate-field.c b/gcc/testsuite/gcc.dg/union-duplicate-field.c
new file mode 100644 (file)
index 0000000..da9a945
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+int a0;
+
+struct S
+{
+    int a1;
+    union {
+        int a0;
+        int a1; /* { dg-error "duplicate member" } */
+        int a2, a3, a4, a5, a6, a7, a8, a9;
+        int a10, a11, a12, a13, a14, a15;
+    };
+};
+
+int f()
+{
+    struct S s;
+    return s.a0;
+}