https://gcc.gnu.org/g:ef83fae50d8f085fe8440bfa595875a2e2329871

commit r15-7470-gef83fae50d8f085fe8440bfa595875a2e2329871
Author: Nathaniel Shead <nathanielosh...@gmail.com>
Date:   Mon Feb 10 22:15:30 2025 +1100

    c++: Fix use-after-free of replaced friend instantiation [PR118807]
    
    When instantiating a friend function, we call register_specialization
    which adds it to the DECL_TEMPLATE_INSTANTIATIONS of the template.
    However, in some circumstances we might immediately call pushdecl and
    find an existing specialisation.  In this case, when reregistering the
    specialisation we also need to update the DECL_TEMPLATE_INSTANTIATIONS
    list so that we don't try to access the freed spec again later.
    
            PR c++/118807
    
    gcc/cp/ChangeLog:
    
            * pt.cc (reregister_specialization): Remove spec from
            DECL_TEMPLATE_INSTANTIATIONS.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/modules/pr118807.C: New test.
    
    Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com>
    Reviewed-by: Jason Merrill <ja...@redhat.com>

Diff:
---
 gcc/cp/pt.cc                            | 11 +++++++++++
 gcc/testsuite/g++.dg/modules/pr118807.C | 11 +++++++++++
 2 files changed, 22 insertions(+)

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 8108bf5de655..f857b3f11804 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -1985,6 +1985,17 @@ reregister_specialization (tree spec, tree tinfo, tree 
new_spec)
       gcc_assert (entry->spec == spec || entry->spec == new_spec);
       gcc_assert (new_spec != NULL_TREE);
       entry->spec = new_spec;
+
+      /* We need to also remove SPEC from DECL_TEMPLATE_INSTANTIATIONS
+        if it was placed there.  */
+      for (tree *inst = &DECL_TEMPLATE_INSTANTIATIONS (elt.tmpl);
+          *inst; inst = &TREE_CHAIN (*inst))
+       if (TREE_VALUE (*inst) == spec)
+         {
+           *inst = TREE_CHAIN (*inst);
+           break;
+         }
+
       return 1;
     }
 
diff --git a/gcc/testsuite/g++.dg/modules/pr118807.C 
b/gcc/testsuite/g++.dg/modules/pr118807.C
new file mode 100644
index 000000000000..a97afb926997
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr118807.C
@@ -0,0 +1,11 @@
+// PR c++/118807
+// { dg-additional-options "-fmodules --param=ggc-min-expand=0 
--param=ggc-min-heapsize=0 -Wno-global-module" }
+
+module;
+template <typename> class basic_streambuf;
+template <typename> struct basic_streambuf {
+  friend void __istream_extract();
+};
+template class basic_streambuf<char>;
+template class basic_streambuf<wchar_t>;
+export module M;

Reply via email to