Hi,

This line of code causes gcc for the AVR target to loop 
for a while and eventually crash after exhausting virtual memory.

   char x[] = { [0xFFFFFF] = 2 };
   
output_pending_init_elements in gcc/c/c-typeck.c ends up in an
infinite loop if elt->purpose is a tree representing an integer
constant equal to max value of TREE_TYPE(constructor_unfilled_index).
For the AVR, that's 0xFFFFFF (PSI mode). 

This happens because output_init_element, in addition to recording
the initialization in a collection, logically increments
constructor_unfilled_index (by generating a size_binop_loc with a
PLUS_EXPR and a int const node representing the number 1, followed by
a fold and a forcefit to the type). This obviously causes a overflow 
if the tree passed in represents an integer constant that's already at 
the max limit.
   
This is not handled in the body of the while (elt) loop, and
constructor_unfilled_index keeps alternating between trees
representing 0 and 0xFFFFFF (max value), eventually running out of 
memory and crashing.
   
I tried to reproduce the problem for x86_64, but I get an ICE even
before output_pending_init_elements is called, apparently because
of PR 57821.
   
The below patch fixes the code to not consider an overflowed 
constructor_unfilled_index to be less than elt->purpose.
   
Is this ok?
   
Regards
Senthil

gcc/c/ChangeLog
2013-08-23  Senthil Kumar Selvaraj  <senthil_kumar.selva...@atmel.com>
        * c-typeck.c (output_pending_init_elements): Handle overflow of
        constructor_unfilled_index.


diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c
index d9ae01c..f87c2a0 100644
--- gcc/c/c-typeck.c
+++ gcc/c/c-typeck.c
@@ -7953,8 +7953,9 @@ output_pending_init_elements (int all, struct obstack * 
braced_init_obstack)
                                 TREE_TYPE (constructor_type),
                                 constructor_unfilled_index, 0, false,
                                 braced_init_obstack);
-         else if (tree_int_cst_lt (constructor_unfilled_index,
-                                   elt->purpose))
+         else if (!TREE_OVERFLOW_P (constructor_unfilled_index)
+              && tree_int_cst_lt (constructor_unfilled_index, 
+                      elt->purpose))
            {
              /* Advance to the next smaller node.  */
              if (elt->left)
@@ -7979,7 +7980,8 @@ output_pending_init_elements (int all, struct obstack * 
braced_init_obstack)
                  while (elt->parent && elt->parent->right == elt)
                    elt = elt->parent;
                  elt = elt->parent;
-                 if (elt && tree_int_cst_lt (constructor_unfilled_index,
+                 if (elt && !TREE_OVERFLOW_P (constructor_unfilled_index)
+                 && tree_int_cst_lt (constructor_unfilled_index,
                                              elt->purpose))
                    {
                      next = elt->purpose;

Reply via email to