[PATCH, fortran][16 Regression] Fix PR124482 SEGV in resolve_cyclic_derived_type

Jerry D <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.fortran
Message-ID <[email protected]>
The attached patch fixes the regression found by Rainer on Solaris Spark. It 
manifests on x86_64 as invalid reads identified by valgrind.

I did confirm the valgrin errors before the patch and that they go away after 
the patch. This is sufficient reason to commit this. I did not hear back from 
Rainer yet in the PR, however if we fix it he will see in his regular builds.

Regression tested on x86_64. Valgrind tested.

OK for mainline?

I will consider backporting to 15 if reasonable. Likely this will be a combining 
of the original fix for 106946 and this one. (easy to do).

Regards,

Jerry

From: Christopher Albert <[email protected]>
Date: Fri, 13 Mar 2026 20:50:07 +0100
Subject: [PATCH] fortran: Fix use-after-free in CLASS component error recovery
  [PR124482]

The error recovery added in r16-8021 (PR106946) freed CLASS container
symbols when removing invalid CLASS components from a derived type.
However, gfc_build_class_symbol reuses existing containers when multiple
components share the same class type and attributes.  Freeing the
container for a failed component also invalidated it for previously
committed components, causing a use-after-free detectable with valgrind
and manifesting as a SEGV on Solaris/SPARC.

Fix by deferring CLASS container cleanup until after all failed
components are unlinked, then freeing the container only if no remaining
component still references it.

gcc/fortran/ChangeLog:

	PR fortran/124482
	* decl.cc (gfc_match_data_decl): Defer CLASS container cleanup
	until after all failed components are unlinked.  Check remaining
	component list before freeing a shared container.

Signed-off-by: Christopher Albert <[email protected]>
pr124482.diff (text/x-patch, 4.1 KB)
From d08632545837e600f290662c4ca5714227abb647 Mon Sep 17 00:00:00 2001
From: Christopher Albert <[email protected]>
Date: Fri, 13 Mar 2026 20:50:07 +0100
Subject: [PATCH] fortran: Fix use-after-free in CLASS component error recovery
 [PR124482]

The error recovery added in r16-8021 (PR106946) freed CLASS container
symbols when removing invalid CLASS components from a derived type.
However, gfc_build_class_symbol reuses existing containers when multiple
components share the same class type and attributes.  Freeing the
container for a failed component also invalidated it for previously
committed components, causing a use-after-free detectable with valgrind
and manifesting as a SEGV on Solaris/SPARC.

Fix by deferring CLASS container cleanup until after all failed
components are unlinked, then freeing the container only if no remaining
component still references it.

gcc/fortran/ChangeLog:

	PR fortran/124482
	* decl.cc (gfc_match_data_decl): Defer CLASS container cleanup
	until after all failed components are unlinked.  Check remaining
	component list before freeing a shared container.

Signed-off-by: Christopher Albert <[email protected]>
---
 gcc/fortran/decl.cc | 51 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 41 insertions(+), 10 deletions(-)

diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
index 551ce86d475..d8aa7d1c06f 100644
--- a/gcc/fortran/decl.cc
+++ b/gcc/fortran/decl.cc
@@ -6994,7 +6994,13 @@ cleanup:
      later calls gfc_undo_symbols, the declaration state is rolled back but
      that helper symbol survives and leaves the component dangling.  Ordinary
      components do not create that extra helper symbol, so leave them in
-     place for the usual follow-up diagnostics.  PR106946.  */
+     place for the usual follow-up diagnostics.  PR106946.
+
+     CLASS containers are shared between components of the same class type
+     and attributes (gfc_build_class_symbol reuses existing containers).
+     We must not free a container that is still referenced by a previously
+     committed component.  Unlink and free the components first, then clean
+     up only orphaned containers.  PR124482.  */
   if (m == MATCH_ERROR && gfc_comp_struct (gfc_current_state ()))
     {
       gfc_symbol *block = gfc_current_block ();
@@ -7006,27 +7012,52 @@ cleanup:
 	  else
 	    prev = &block->components;
 
+	  /* Record the CLASS container from the removed components.
+	     Normally all components in one declaration share a single
+	     container, but per-variable array specs can produce
+	     additional ones; any beyond the first are harmlessly
+	     leaked until namespace destruction.  */
+	  gfc_symbol *fclass_container = NULL;
+
 	  while (*prev)
 	    {
 	      gfc_component *c = *prev;
 	      if (c->ts.type == BT_CLASS && c->ts.u.derived
 		  && c->ts.u.derived->attr.is_class)
 		{
-		  /* Unlink this CLASS component.  */
 		  *prev = c->next;
-
-		  /* Remove the CLASS container from the namespace.  */
-		  gfc_symbol *fclass = c->ts.u.derived;
-		  if (gfc_find_symtree (fclass->ns->sym_root, fclass->name))
-		    gfc_delete_symtree (&fclass->ns->sym_root, fclass->name);
-		  gfc_release_symbol (fclass);
-
-		  /* Free the component structure.  */
+		  if (!fclass_container)
+		    fclass_container = c->ts.u.derived;
+		  c->ts.u.derived = NULL;
 		  gfc_free_component (c);
 		}
 	      else
 		prev = &c->next;
 	    }
+
+	  /* Free the container only if no remaining component still
+	     references it.  CLASS containers are shared between
+	     components of the same class type and attributes
+	     (gfc_build_class_symbol reuses existing ones).  */
+	  if (fclass_container)
+	    {
+	      bool shared = false;
+	      for (gfc_component *q = block->components; q; q = q->next)
+		if (q->ts.type == BT_CLASS
+		    && q->ts.u.derived == fclass_container)
+		  {
+		    shared = true;
+		    break;
+		  }
+	      if (!shared)
+		{
+		  if (gfc_find_symtree (fclass_container->ns->sym_root,
+					fclass_container->name))
+		    gfc_delete_symtree (&fclass_container->ns->sym_root,
+					fclass_container->name);
+		  gfc_release_symbol (fclass_container);
+		}
+	    }
 	}
     }
 
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.