[binutils-gdb] [gdb/symtab] Add assert in free_cached_comp_units constructor

Tom de Vries via Gdb-cvs <[email protected]> Fri, 29 May 2026 15:58:16 +0000 (GMT)
Newsgroups gmane.comp.gdb.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=b083976272bd663ed036692e54796870b3bf6c89

commit b083976272bd663ed036692e54796870b3bf6c89
Author: Tom de Vries <[email protected]>
Date:   Fri May 29 17:58:12 2026 +0200

    [gdb/symtab] Add assert in free_cached_comp_units constructor
    
    I wrote a patch containing:
    ...
          dw2_instantiate_symtab (cu->per_cu, ...);
    ...
    and ran into a use-after-free at a following use of cu.
    
    The problem is that dw2_instantiate_symtab contains:
    ...
          free_cached_comp_units freer (per_objfile);
    ...
    and that the destructor does:
    ...
      ~free_cached_comp_units ()
      {
        m_per_objfile->remove_all_cus ();
      }
    ...
    which also frees the cu we used in the cu->per_cu argument to
    dw2_instantiate_symtab.
    
    Detect this situation using an assert in the free_cached_comp_units
    constructor.
    
    Tested on aarch64-linux.
    
    Approved-By: Tom Tromey <[email protected]>

Diff:
---
 gdb/dwarf2/read.c | 3 +++
 gdb/dwarf2/read.h | 6 ++++++
 2 files changed, 9 insertions(+)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 742be7656b1..0d313f62f4a 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -902,6 +902,9 @@ public:
   explicit free_cached_comp_units (dwarf2_per_objfile *per_objfile)
     : m_per_objfile (per_objfile)
   {
+    /* The destructor frees all cached comp units, including ones currently
+       cached, so check that there are no currently cached comp units.  */
+    gdb_assert (m_per_objfile->nr_of_cus () == 0);
   }
 
   ~free_cached_comp_units ()
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index 15dd2abf3a1..603fe089d6a 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -969,6 +969,12 @@ struct dwarf2_per_objfile
   /* Free all cached compilation units.  */
   void remove_all_cus ();
 
+  /* Return the number of cached compilation units.  */
+  size_t nr_of_cus () const
+  {
+    return m_dwarf2_cus.size ();
+  }
+
   /* Increase the age counter on each CU compilation unit and free
      any that are too old.  */
   void age_comp_units ();