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 <[email protected]>
* 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;