]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
PR 33821 use after free commit e6357caf7579
authorAlan Modra <amodra@gmail.com>
Thu, 22 Jan 2026 06:41:35 +0000 (17:11 +1030)
committerAlan Modra <amodra@gmail.com>
Thu, 22 Jan 2026 09:06:49 +0000 (19:36 +1030)
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.

ld/emultempl/xtensaelf.em
ld/ldlang.c
ld/ldlang.h

index 86485a9fdf6f03954a943aad2883d40ab1f6e5d8..99d159658ce398e9cfc229c6b36c53eec519fb28 100644 (file)
@@ -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);
 }
 
 
index 0ef33e8a4e639d8f96627e1e074898a34a9e53c2..c0d729811ecf921c71227fdc421a6d7a047567b3 100644 (file)
@@ -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
index f9010e277856edae4e66138d5c7f97f70a9fe32d..36f3c03955dadfa6ccb90ca165a988f8cebe5dfc 100644 (file)
@@ -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