[binutils-gdb] PR 33821 use after free commit e6357caf7579
Alan Modra
amodra@sourceware.org
Thu Jan 22 09:09:14 GMT 2026
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d75f191dc631664e4f18c6938f0cb72f1f50c34a
commit d75f191dc631664e4f18c6938f0cb72f1f50c34a
Author: Alan Modra <amodra@gmail.com>
Date: Thu Jan 22 17:11:35 2026 +1030
PR 33821 use after free commit e6357caf7579
reset_resolved_wilds didn't clear out matching_sections in output
sections with constraint -1. Fix that and tidy call sites of
obstack_init and obstack_free for matching_obstack so that the obstack
is allocated later and freed completely. Also tidy ptroot.
PR 33821
* ldlang.c (the_root): Delete, replacing with..
(ptroot): ..this, no longer a pointer. Update all uses.
(lang_for_each_statement_worker): Add "constrained" param.
Ignore os.constraint if false.
(reset_resolved_wilds): Use lang_for_each_statement_worker.
Move obstack_init..
(lang_init): ..and this obstack_init of matching_obstack..
(resolve_wilds): ..to here.
* ldlang.h (lang_for_each_statement_worker): Update declaration.
(lang_for_each_statement): Update.
* emultempl/xtensaelf.em: Update lang_for_each_statement_worker
calls throughout.
Diff:
---
ld/emultempl/xtensaelf.em | 14 +++++++++-----
ld/ldlang.c | 33 ++++++++++++++++++---------------
ld/ldlang.h | 4 ++--
3 files changed, 29 insertions(+), 22 deletions(-)
diff --git a/ld/emultempl/xtensaelf.em b/ld/emultempl/xtensaelf.em
index 86485a9fdf6..99d159658ce 100644
--- a/ld/emultempl/xtensaelf.em
+++ b/ld/emultempl/xtensaelf.em
@@ -1047,7 +1047,8 @@ xtensa_colocate_literals (reloc_deps_graph *deps,
iter_stack_update (stack_p);
}
- lang_for_each_statement_worker (xtensa_ldlang_clear_addresses, statement);
+ lang_for_each_statement_worker (xtensa_ldlang_clear_addresses,
+ statement, true);
}
@@ -1283,7 +1284,8 @@ input_section_linked (asection *sec)
{
input_section_found = false;
input_section_target = sec;
- lang_for_each_statement_worker (input_section_linked_worker, stat_ptr->head);
+ lang_for_each_statement_worker (input_section_linked_worker,
+ stat_ptr->head, true);
return input_section_found;
}
@@ -1505,7 +1507,8 @@ xtensa_wild_group_interleave_callback (lang_statement_union_type *statement)
static void
xtensa_wild_group_interleave (lang_statement_union_type *s)
{
- lang_for_each_statement_worker (xtensa_wild_group_interleave_callback, s);
+ lang_for_each_statement_worker (xtensa_wild_group_interleave_callback,
+ s, true);
}
@@ -1664,7 +1667,7 @@ xtensa_colocate_output_literals_callback (lang_statement_union_type *statement)
ld_xtensa_insert_page_offsets (0, statement, deps,
xtensa_use_literal_pages);
lang_for_each_statement_worker (xtensa_ldlang_clear_addresses,
- statement);
+ statement, true);
}
/* Clean up. */
@@ -1676,7 +1679,8 @@ xtensa_colocate_output_literals_callback (lang_statement_union_type *statement)
static void
xtensa_colocate_output_literals (lang_statement_union_type *s)
{
- lang_for_each_statement_worker (xtensa_colocate_output_literals_callback, s);
+ lang_for_each_statement_worker (xtensa_colocate_output_literals_callback,
+ s, true);
}
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 0ef33e8a4e6..c0d729811ec 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -846,7 +846,7 @@ struct prefixtree
/* We always have a root node in the prefix tree. It corresponds to the
empty prefix. E.g. a glob like "*" would sit in this root. */
-static struct prefixtree the_root, *ptroot = &the_root;
+static struct prefixtree ptroot;
/* Given a prefix tree in *TREE, corresponding to prefix P, find or
INSERT the tree node corresponding to prefix P+C. */
@@ -897,7 +897,7 @@ insert_prefix_tree (lang_wild_statement_type *stmt)
{
/* If we have no section_list (no wildcards in the wild STMT),
then every section name will match, so add this to the root. */
- pt_add_stmt (ptroot, stmt);
+ pt_add_stmt (&ptroot, stmt);
return;
}
@@ -905,7 +905,7 @@ insert_prefix_tree (lang_wild_statement_type *stmt)
{
const char *name = sec->spec.name ? sec->spec.name : "*";
char c;
- t = ptroot;
+ t = &ptroot;
for (; (c = *name); name++)
{
if (c == '*' || c == '[' || c == '?')
@@ -949,7 +949,7 @@ debug_prefix_tree_rec (struct prefixtree *t, int indent)
static void
debug_prefix_tree (void)
{
- debug_prefix_tree_rec (ptroot, 2);
+ debug_prefix_tree_rec (&ptroot, 2);
}
/* Like strcspn() but start to look from the end to beginning of
@@ -1012,7 +1012,7 @@ resolve_wild_sections (lang_input_statement_type *file)
{
const char *sname = bfd_section_name (s);
char c = 1;
- struct prefixtree *t = ptroot;
+ struct prefixtree *t = &ptroot;
//printf (" YYY consider %s of %s\n", sname, file->the_bfd->filename);
do
{
@@ -1039,6 +1039,7 @@ resolve_wild_sections (lang_input_statement_type *file)
static void
resolve_wilds (void)
{
+ obstack_init (&matching_obstack);
LANG_FOR_EACH_INPUT_STATEMENT (f)
{
//printf("XXX %s\n", f->filename);
@@ -1085,11 +1086,12 @@ walk_wild (lang_wild_statement_type *s, callback_t callback, void *data)
/* lang_for_each_statement walks the parse tree and calls the provided
function for each node, except those inside output section statements
- with constraint set to -1. */
+ with constraint set to -1 if CONSTRAINED is true. */
void
lang_for_each_statement_worker (void (*func) (lang_statement_union_type *),
- lang_statement_union_type *s)
+ lang_statement_union_type *s,
+ bool constrained)
{
for (; s != NULL; s = s->header.next)
{
@@ -1098,20 +1100,23 @@ lang_for_each_statement_worker (void (*func) (lang_statement_union_type *),
switch (s->header.type)
{
case lang_constructors_statement_enum:
- lang_for_each_statement_worker (func, constructor_list.head);
+ lang_for_each_statement_worker (func, constructor_list.head,
+ constrained);
break;
case lang_output_section_statement_enum:
- if (s->output_section_statement.constraint != -1)
+ if (!constrained || s->output_section_statement.constraint != -1)
lang_for_each_statement_worker
- (func, s->output_section_statement.children.head);
+ (func, s->output_section_statement.children.head, constrained);
break;
case lang_wild_statement_enum:
lang_for_each_statement_worker (func,
- s->wild_statement.children.head);
+ s->wild_statement.children.head,
+ constrained);
break;
case lang_group_statement_enum:
lang_for_each_statement_worker (func,
- s->group_statement.children.head);
+ s->group_statement.children.head,
+ constrained);
break;
case lang_data_statement_enum:
case lang_reloc_statement_enum:
@@ -1391,7 +1396,6 @@ lang_init (bool object_only)
{
obstack_begin (&stat_obstack, 1000);
obstack_init (&pt_obstack);
- obstack_init (&matching_obstack);
}
stat_ptr = &statement_list;
@@ -8316,9 +8320,8 @@ reset_one_wild (lang_statement_union_type *statement)
static void
reset_resolved_wilds (void)
{
- lang_for_each_statement (reset_one_wild);
+ lang_for_each_statement_worker (reset_one_wild, statement_list.head, false);
obstack_free (&matching_obstack, NULL);
- obstack_init (&matching_obstack);
}
/* For each output section statement, splice any entries on the
diff --git a/ld/ldlang.h b/ld/ldlang.h
index f9010e27785..36f3c03955d 100644
--- a/ld/ldlang.h
+++ b/ld/ldlang.h
@@ -648,7 +648,7 @@ extern void lang_add_reloc
(bfd_reloc_code_real_type, reloc_howto_type *, asection *, const char *,
union etree_union *);
extern void lang_for_each_statement_worker
- (void (*) (lang_statement_union_type *), lang_statement_union_type *);
+ (void (*) (lang_statement_union_type *), lang_statement_union_type *, bool);
extern void *stat_alloc
(size_t);
extern void stat_free
@@ -793,7 +793,7 @@ bfd_input_just_syms (const bfd *abfd)
static inline void
lang_for_each_statement (void (*func) (lang_statement_union_type *))
{
- lang_for_each_statement_worker (func, statement_list.head);
+ lang_for_each_statement_worker (func, statement_list.head, true);
}
static inline void
More information about the Binutils-cvs
mailing list