[binutils-gdb] BFD/aout: Sanitize back end flavour for external symbols retrieval

Maciej W. Rozycki macro@sourceware.org
Fri Feb 20 17:42:17 GMT 2026


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=1dbbff036491f3277fefb6ffba95edaa02a9a3b8

commit 1dbbff036491f3277fefb6ffba95edaa02a9a3b8
Author: Maciej W. Rozycki <macro@redhat.com>
Date:   Fri Feb 20 17:29:50 2026 +0000

    BFD/aout: Sanitize back end flavour for external symbols retrieval
    
    Make `aout_get_external_symbols' return unsuccessfully right away if
    called for a non-aout BFD, preventing a crash from an attempt to access
    inexistent ->tdata.aout_data->a (`struct aoutdata') struct member.  Add
    assertions at call sites to track potential invalid usage.
    
    This converts a segmentation fault to an assertion failure followed by
    graceful termination:
    
    .../ld/ld-new: BFD (GNU Binutils) 2.45.50.20251209 assertion fail .../bfd/aoutx.h:3449
    .../ld/ld-new: tmpdir/ab.a: error adding symbols: file in wrong format
    
    with an upcoming test case:
    
    FAIL: CRIS regular archive link (implicit emulation)
    
    where a `cris-aout' target linker invocation:
    
    $ .../ld/ld-new -o tmpdir/abci -e ff tmpdir/abc.o tmpdir/ab.a
    
    lands in `_bfd_generic_link_add_archive_symbols' with an inconsistent
    state between an archive's BFD and its member's BFD:
    
    Breakpoint 1, _bfd_generic_link_add_archive_symbols (abfd=0x100264700,
        info=0x100253110 <link_info>,
        checkfn=0x10009ac80 <aout_link_check_archive_element>)
        at .../bfd/linker.c:1020
    1020              if (! (*checkfn) (element, info, h, arsym->name, &needed))
    (gdb) print *abfd
    $1 = {filename = 0x1002b6200 "tmpdir/ab.a",
      xvec = 0x10028d650 <cris_aout_vec>, iostream = 0x1002a47d0,
    [...]
    (gdb) print *element
    $2 = {filename = 0x1002ccfb0 "a.o", xvec = 0x10028ea30 <cris_elf32_us_vec>,
      iostream = 0x0, iovec = 0x10028ace8 <cache_iovec>, lru_prev = 0x0,
    [...]
    (gdb)

Diff:
---
 bfd/aoutx.h | 12 ++++++++++++
 bfd/pdp11.c | 12 ++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/bfd/aoutx.h b/bfd/aoutx.h
index b1914d38118..f081a6c5054 100644
--- a/bfd/aoutx.h
+++ b/bfd/aoutx.h
@@ -1288,6 +1288,9 @@ NAME (aout, set_section_contents) (bfd *abfd,
 static bool
 aout_get_external_symbols (bfd *abfd)
 {
+  if (bfd_get_flavour (abfd) != bfd_target_aout_flavour)
+    return false;
+
   if (obj_aout_external_syms (abfd) == NULL)
     {
       bfd_size_type count;
@@ -1731,6 +1734,8 @@ NAME (aout, slurp_symbol_table) (bfd *abfd)
   aout_symbol_type *cached;
   bfd_size_type cached_size;
 
+  BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
   /* If there's no work to be done, don't do any.  */
   if (obj_aout_symbols (abfd) != NULL)
     return true;
@@ -2598,6 +2603,8 @@ NAME (aout, read_minisymbols) (bfd *abfd,
 			       void * *minisymsp,
 			       unsigned int *sizep)
 {
+  BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
   if (dynamic)
     /* We could handle the dynamic symbols here as well, but it's
        easier to hand them off.  */
@@ -3215,6 +3222,8 @@ aout_link_free_symbols (bfd *abfd)
 static bool
 aout_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 {
+  BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
   if (! aout_get_external_symbols (abfd))
     return false;
   if (! aout_link_add_symbols (abfd, info))
@@ -3437,6 +3446,8 @@ aout_link_check_archive_element (bfd *abfd,
   bfd *oldbfd;
   bool needed;
 
+  BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
   if (!aout_get_external_symbols (abfd))
     return false;
 
@@ -5261,6 +5272,7 @@ static bool
 aout_link_input_bfd (struct aout_final_link_info *flaginfo, bfd *input_bfd)
 {
   BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object);
+  BFD_ASSERT (bfd_get_flavour (input_bfd) == bfd_target_aout_flavour);
 
   /* If this is a dynamic object, it may need special handling.  */
   if ((input_bfd->flags & DYNAMIC) != 0
diff --git a/bfd/pdp11.c b/bfd/pdp11.c
index 552c0484992..6472e2741f1 100644
--- a/bfd/pdp11.c
+++ b/bfd/pdp11.c
@@ -1264,6 +1264,9 @@ NAME (aout, set_section_contents) (bfd *abfd,
 static bool
 aout_get_external_symbols (bfd *abfd)
 {
+  if (bfd_get_flavour (abfd) != bfd_target_aout_flavour)
+    return false;
+
   if (obj_aout_external_syms (abfd) == NULL)
     {
       bfd_size_type count;
@@ -1604,6 +1607,8 @@ NAME (aout, slurp_symbol_table) (bfd *abfd)
   aout_symbol_type *cached;
   bfd_size_type cached_size;
 
+  BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
   /* If there's no work to be done, don't do any.  */
   if (obj_aout_symbols (abfd) != NULL)
     return true;
@@ -2235,6 +2240,8 @@ NAME (aout, read_minisymbols) (bfd *abfd,
 			       void * *minisymsp,
 			       unsigned int *sizep)
 {
+  BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
   if (dynamic)
     /* We could handle the dynamic symbols here as well, but it's
        easier to hand them off.  */
@@ -2637,6 +2644,8 @@ NAME (aout, link_add_symbols) (bfd *abfd, struct bfd_link_info *info)
 static bool
 aout_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
 {
+  BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
   if (! aout_get_external_symbols (abfd))
     return false;
   if (! aout_link_add_symbols (abfd, info))
@@ -2801,6 +2810,8 @@ aout_link_check_archive_element (bfd *abfd,
   bfd *oldbfd;
   bool needed;
 
+  BFD_ASSERT (bfd_get_flavour (abfd) == bfd_target_aout_flavour);
+
   if (!aout_get_external_symbols (abfd))
     return false;
 
@@ -3698,6 +3709,7 @@ static bool
 aout_link_input_bfd (struct aout_final_link_info *flaginfo, bfd *input_bfd)
 {
   BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object);
+  BFD_ASSERT (bfd_get_flavour (input_bfd) == bfd_target_aout_flavour);
 
   /* If this is a dynamic object, it may need special handling.  */
   if ((input_bfd->flags & DYNAMIC) != 0


More information about the Binutils-cvs mailing list