From: Alan Modra Date: Thu, 22 Jan 2026 06:41:35 +0000 (+1030) Subject: PR 33821 use after free commit e6357caf7579 X-Git-Tag: binutils-2_46~133 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d75f191dc631664e4f18c6938f0cb72f1f50c34a;p=thirdparty%2Fbinutils-gdb.git 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 --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