]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Fix use-after-free of replaced friend instantiation [PR118807]
authorNathaniel Shead <nathanieloshead@gmail.com>
Mon, 10 Feb 2025 11:15:30 +0000 (22:15 +1100)
committerNathaniel Shead <nathanieloshead@gmail.com>
Tue, 11 Feb 2025 11:26:52 +0000 (22:26 +1100)
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 <nathanieloshead@gmail.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/pt.cc
gcc/testsuite/g++.dg/modules/pr118807.C [new file with mode: 0644]

index 8108bf5de6555bca493b64c3784250acbfd47b72..f857b3f11804df1da2f3b51943d32894c337a7c6 100644 (file)
@@ -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 (file)
index 0000000..a97afb9
--- /dev/null
@@ -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;