Fix obstack use-after-free problems in C frontend, PR69522
c/ PR c/69522 * c-parser.c (c_parser_braced_init): New arg outer_obstack. All callers changed. If nested_p is true, use it to call finish_implicit_inits. * c-tree.h (finish_implicit_inits): Declare. * c-typeck.c (finish_implicit_inits): New function. Move code from ... (push_init_level): ... here. (set_designator, process_init_element): Call finish_implicit_inits. testsuite/ PR c/69522 gcc.dg/pr69522.c: New test. From-SVN: r233366
This commit is contained in:
parent
38d795d27c
commit
16595a1f28
@ -1,3 +1,15 @@
|
||||
2016-02-12 Bernd Schmidt <bschmidt@redhat.com>
|
||||
|
||||
PR c/69522
|
||||
* c-parser.c (c_parser_braced_init): New arg outer_obstack. All
|
||||
callers changed. If nested_p is true, use it to call
|
||||
finish_implicit_inits.
|
||||
* c-tree.h (finish_implicit_inits): Declare.
|
||||
* c-typeck.c (finish_implicit_inits): New function. Move code
|
||||
from ...
|
||||
(push_init_level): ... here.
|
||||
(set_designator, process_init_element): Call finish_implicit_inits.
|
||||
|
||||
2016-02-11 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c/69768
|
||||
|
@ -1293,7 +1293,8 @@ static tree c_parser_simple_asm_expr (c_parser *);
|
||||
static tree c_parser_attributes (c_parser *);
|
||||
static struct c_type_name *c_parser_type_name (c_parser *);
|
||||
static struct c_expr c_parser_initializer (c_parser *);
|
||||
static struct c_expr c_parser_braced_init (c_parser *, tree, bool);
|
||||
static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
|
||||
struct obstack *);
|
||||
static void c_parser_initelt (c_parser *, struct obstack *);
|
||||
static void c_parser_initval (c_parser *, struct c_expr *,
|
||||
struct obstack *);
|
||||
@ -4307,7 +4308,7 @@ static struct c_expr
|
||||
c_parser_initializer (c_parser *parser)
|
||||
{
|
||||
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
|
||||
return c_parser_braced_init (parser, NULL_TREE, false);
|
||||
return c_parser_braced_init (parser, NULL_TREE, false, NULL);
|
||||
else
|
||||
{
|
||||
struct c_expr ret;
|
||||
@ -4327,7 +4328,8 @@ c_parser_initializer (c_parser *parser)
|
||||
top-level initializer in a declaration. */
|
||||
|
||||
static struct c_expr
|
||||
c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
|
||||
c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
|
||||
struct obstack *outer_obstack)
|
||||
{
|
||||
struct c_expr ret;
|
||||
struct obstack braced_init_obstack;
|
||||
@ -4336,7 +4338,10 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p)
|
||||
gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
|
||||
c_parser_consume_token (parser);
|
||||
if (nested_p)
|
||||
push_init_level (brace_loc, 0, &braced_init_obstack);
|
||||
{
|
||||
finish_implicit_inits (brace_loc, outer_obstack);
|
||||
push_init_level (brace_loc, 0, &braced_init_obstack);
|
||||
}
|
||||
else
|
||||
really_start_incremental_init (type);
|
||||
if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
|
||||
@ -4594,7 +4599,8 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
|
||||
location_t loc = c_parser_peek_token (parser)->location;
|
||||
|
||||
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
|
||||
init = c_parser_braced_init (parser, NULL_TREE, true);
|
||||
init = c_parser_braced_init (parser, NULL_TREE, true,
|
||||
braced_init_obstack);
|
||||
else
|
||||
{
|
||||
init = c_parser_expr_no_commas (parser, after);
|
||||
@ -8083,7 +8089,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
|
||||
error_at (type_loc, "compound literal has variable size");
|
||||
type = error_mark_node;
|
||||
}
|
||||
init = c_parser_braced_init (parser, type, false);
|
||||
init = c_parser_braced_init (parser, type, false, NULL);
|
||||
finish_init ();
|
||||
maybe_warn_string_init (type_loc, type, init);
|
||||
|
||||
|
@ -625,6 +625,7 @@ extern void maybe_warn_string_init (location_t, tree, struct c_expr);
|
||||
extern void start_init (tree, tree, int);
|
||||
extern void finish_init (void);
|
||||
extern void really_start_incremental_init (tree);
|
||||
extern void finish_implicit_inits (location_t, struct obstack *);
|
||||
extern void push_init_level (location_t, int, struct obstack *);
|
||||
extern struct c_expr pop_init_level (location_t, int, struct obstack *);
|
||||
extern void set_init_index (location_t, tree, tree, struct obstack *);
|
||||
|
@ -7548,6 +7548,30 @@ really_start_incremental_init (tree type)
|
||||
}
|
||||
}
|
||||
|
||||
/* Called when we see an open brace for a nested initializer. Finish
|
||||
off any pending levels with implicit braces. */
|
||||
void
|
||||
finish_implicit_inits (location_t loc, struct obstack *braced_init_obstack)
|
||||
{
|
||||
while (constructor_stack->implicit)
|
||||
{
|
||||
if (RECORD_OR_UNION_TYPE_P (constructor_type)
|
||||
&& constructor_fields == 0)
|
||||
process_init_element (input_location,
|
||||
pop_init_level (loc, 1, braced_init_obstack),
|
||||
true, braced_init_obstack);
|
||||
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
|
||||
&& constructor_max_index
|
||||
&& tree_int_cst_lt (constructor_max_index,
|
||||
constructor_index))
|
||||
process_init_element (input_location,
|
||||
pop_init_level (loc, 1, braced_init_obstack),
|
||||
true, braced_init_obstack);
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Push down into a subobject, for initialization.
|
||||
If this is for an explicit set of braces, IMPLICIT is 0.
|
||||
If it is because the next element belongs at a lower level,
|
||||
@ -7560,33 +7584,6 @@ push_init_level (location_t loc, int implicit,
|
||||
struct constructor_stack *p;
|
||||
tree value = NULL_TREE;
|
||||
|
||||
/* If we've exhausted any levels that didn't have braces,
|
||||
pop them now. If implicit == 1, this will have been done in
|
||||
process_init_element; do not repeat it here because in the case
|
||||
of excess initializers for an empty aggregate this leads to an
|
||||
infinite cycle of popping a level and immediately recreating
|
||||
it. */
|
||||
if (implicit != 1)
|
||||
{
|
||||
while (constructor_stack->implicit)
|
||||
{
|
||||
if (RECORD_OR_UNION_TYPE_P (constructor_type)
|
||||
&& constructor_fields == 0)
|
||||
process_init_element (input_location,
|
||||
pop_init_level (loc, 1, braced_init_obstack),
|
||||
true, braced_init_obstack);
|
||||
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
|
||||
&& constructor_max_index
|
||||
&& tree_int_cst_lt (constructor_max_index,
|
||||
constructor_index))
|
||||
process_init_element (input_location,
|
||||
pop_init_level (loc, 1, braced_init_obstack),
|
||||
true, braced_init_obstack);
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unless this is an explicit brace, we need to preserve previous
|
||||
content if any. */
|
||||
if (implicit)
|
||||
@ -8013,6 +8010,7 @@ set_designator (location_t loc, int array,
|
||||
}
|
||||
|
||||
constructor_designated = 1;
|
||||
finish_implicit_inits (loc, braced_init_obstack);
|
||||
push_init_level (loc, 2, braced_init_obstack);
|
||||
return 0;
|
||||
}
|
||||
@ -9396,6 +9394,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit,
|
||||
p = p->next;
|
||||
if (!p)
|
||||
break;
|
||||
finish_implicit_inits (loc, braced_init_obstack);
|
||||
push_init_level (loc, 2, braced_init_obstack);
|
||||
p->stack = constructor_stack;
|
||||
if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
|
||||
|
@ -1,3 +1,8 @@
|
||||
2016-02-12 Bernd Schmidt <bschmidt@redhat.com>
|
||||
|
||||
PR c/69522
|
||||
gcc.dg/pr69522.c: New test.
|
||||
|
||||
2016-02-12 Patrick Palka <ppalka@gcc.gnu.org>
|
||||
|
||||
PR c++/69098
|
||||
|
9
gcc/testsuite/gcc.dg/pr69522.c
Normal file
9
gcc/testsuite/gcc.dg/pr69522.c
Normal file
@ -0,0 +1,9 @@
|
||||
/* { dg-do compile } */
|
||||
struct str {};
|
||||
struct {
|
||||
struct str b;
|
||||
float c[1];
|
||||
int d[1];
|
||||
float e[2];
|
||||
int f[1];
|
||||
} a = {{}, 0, {0.5}, 0, 0, {0}};
|
Loading…
x
Reference in New Issue
Block a user