[gcc r16-8320] Fortran: Fix use-after-free in gfc_fixup_sibling_symbols [PR95879]

Paul Thomas pault@gcc.gnu.org
Sat Mar 28 09:09:05 GMT 2026


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

commit r16-8320-gee931e5b7eab59916f4dd77a4ad20c1202153036
Author: Paul Thomas <pault@gcc.gnu.org>
Date:   Sat Mar 28 09:08:54 2026 +0000

    Fortran:  Fix use-after-free in gfc_fixup_sibling_symbols [PR95879]
    
    2026-03-28  Paul Thomas  <pault@gcc.gnu.org>
    
    gcc/fortran
            PR fortran/95879
            * parse.cc (fixup_st_func_formals): New function to update
            statement function formal argument lists referencing a symbol
            about to be freed.
            (gfc_fixup_sibling_symbols): Call fixup_st_func_formals before
            gfc_release_symbol.
    
    gcc/testsuite
            PR fortran/95879
            * gfortran.dg/pr95879.f90: New test.

Diff:
---
 gcc/fortran/parse.cc                  | 27 +++++++++++++++++++++++++++
 gcc/testsuite/gfortran.dg/pr95879.f90 | 30 ++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index e397ea6015cd..a41bf090c339 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -6853,6 +6853,28 @@ parse_executable (gfc_statement st)
 }
 
 
+/* Update statement function formal argument lists that reference OLD_SYM
+   to point to NEW_SYM instead.  This prevents use-after-free when
+   gfc_fixup_sibling_symbols replaces and frees a symbol that is also
+   used as a statement function dummy argument (PR95879).  */
+
+static void
+fixup_st_func_formals (gfc_symtree *st, gfc_symbol *old_sym,
+		       gfc_symbol *new_sym)
+{
+  if (st == NULL)
+    return;
+
+  fixup_st_func_formals (st->left, old_sym, new_sym);
+  fixup_st_func_formals (st->right, old_sym, new_sym);
+
+  if (st->n.sym && st->n.sym->attr.proc == PROC_ST_FUNCTION)
+    for (gfc_formal_arglist *fa = st->n.sym->formal; fa; fa = fa->next)
+      if (fa->sym == old_sym)
+	fa->sym = new_sym;
+}
+
+
 /* Fix the symbols for sibling functions.  These are incorrectly added to
    the child namespace as the parser didn't know about this procedure.  */
 
@@ -6907,6 +6929,11 @@ gfc_fixup_sibling_symbols (gfc_symbol *sym, gfc_namespace *siblings)
 	  sym->refs++;
 	  if (imported)
 	    sym->attr.imported = 1;
+
+	  /* Update statement function formal argument lists that still
+	     reference old_sym before releasing it (PR95879).  */
+	  fixup_st_func_formals (ns->sym_root, old_sym, sym);
+
 	  gfc_release_symbol (old_sym);
 	}
 
diff --git a/gcc/testsuite/gfortran.dg/pr95879.f90 b/gcc/testsuite/gfortran.dg/pr95879.f90
new file mode 100644
index 000000000000..67c8af0de3bc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr95879.f90
@@ -0,0 +1,30 @@
+! { dg-do compile }
+! { dg-options "-std=f2018" }
+! PR fortran/95879
+! Contributed by G. Steinmetz <gscfq@t-online.de>
+!
+! Use-after-free in gfc_resolve_formal_arglist when a contained subroutine
+! has a statement function whose dummy argument name matches a symbol
+! replaced by gfc_fixup_sibling_symbols.
+
+module m1
+contains
+   integer function f(x) bind(c)
+      use iso_c_binding
+   contains
+      subroutine s
+         c_funloc(f) = x  ! { dg-warning "Obsolescent feature: Statement function" }
+      end
+   end
+end
+
+module m2
+contains
+   integer function f(x)
+      use iso_c_binding
+   contains
+      subroutine s
+         c_funloc(f) = x  ! { dg-warning "Obsolescent feature: Statement function" }
+      end
+   end
+end


More information about the Gcc-cvs mailing list