]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fortran: avoid several NULL pointer dereferences during error recovery
authorHarald Anlauf <anlauf@gmx.de>
Mon, 27 Dec 2021 22:06:18 +0000 (23:06 +0100)
committerHarald Anlauf <anlauf@gmx.de>
Thu, 13 Jan 2022 21:02:02 +0000 (22:02 +0100)
gcc/fortran/ChangeLog:

PR fortran/102332
* expr.c (gfc_get_variable_expr): Avoid NULL pointer dereferences
during handling of errors with invalid uses of CLASS variables.
* match.c (select_type_set_tmp): Likewise.
* primary.c (gfc_match_varspec): Likewise.
* resolve.c (resolve_variable): Likewise.
(resolve_select_type): Likewise.

gcc/testsuite/ChangeLog:

PR fortran/102332
* gfortran.dg/pr102332.f90: New test.

(cherry picked from commit d8f6c48ccb85ecc0d97a84c32b7a1b8f43c64fe4)

gcc/fortran/expr.c
gcc/fortran/match.c
gcc/fortran/primary.c
gcc/fortran/resolve.c
gcc/testsuite/gfortran.dg/pr102332.f90 [new file with mode: 0644]

index 95b351539419f173645d4abaf8bd91ef25232ee9..e8c7c212e70842a03523872e55f0f926bc46cb2b 100644 (file)
@@ -5149,7 +5149,8 @@ gfc_get_variable_expr (gfc_symtree *var)
 
   if (var->n.sym->attr.flavor != FL_PROCEDURE
       && ((var->n.sym->as != NULL && var->n.sym->ts.type != BT_CLASS)
-          || (var->n.sym->ts.type == BT_CLASS && CLASS_DATA (var->n.sym)
+          || (var->n.sym->ts.type == BT_CLASS && var->n.sym->ts.u.derived
+              && CLASS_DATA (var->n.sym)
               && CLASS_DATA (var->n.sym)->as)))
     {
       e->rank = var->n.sym->ts.type == BT_CLASS
index ef6c86af2f957323d1ae696c891f4feea8e142f8..7d06e0eef30cf2c3c29ad9f02fce854b43bdaaf2 100644 (file)
@@ -6338,7 +6338,8 @@ select_type_set_tmp (gfc_typespec *ts)
       sym = tmp->n.sym;
       gfc_add_type (sym, ts, NULL);
 
-      if (selector->ts.type == BT_CLASS && selector->attr.class_ok)
+      if (selector->ts.type == BT_CLASS && selector->attr.class_ok
+         && selector->ts.u.derived && CLASS_DATA (selector))
        {
          sym->attr.pointer
                = CLASS_DATA (selector)->attr.class_pointer;
index b03961a99816abb5b40463715bac2faddbb268b0..78c4b634db333fcb9f61d9fbd30bc5aa7138cbd8 100644 (file)
@@ -2172,6 +2172,7 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
          && !(gfc_matching_procptr_assignment
               && sym->attr.flavor == FL_PROCEDURE))
       || (sym->ts.type == BT_CLASS && sym->attr.class_ok
+         && sym->ts.u.derived && CLASS_DATA (sym)
          && (CLASS_DATA (sym)->attr.dimension
              || CLASS_DATA (sym)->attr.codimension)))
     {
index 591b36fa4bd95f5d7b2449bfaf50f34eaa84d971..9104b17988b700970ec73ba645c7ebd20af5c90f 100644 (file)
@@ -5677,6 +5677,8 @@ resolve_variable (gfc_expr *e)
      can't be translated that way.  */
   if (sym->assoc && e->rank == 0 && e->ref && sym->ts.type == BT_CLASS
       && sym->assoc->target && sym->assoc->target->ts.type == BT_CLASS
+      && sym->assoc->target->ts.u.derived
+      && CLASS_DATA (sym->assoc->target)
       && CLASS_DATA (sym->assoc->target)->as)
     {
       gfc_ref *ref = e->ref;
@@ -5741,7 +5743,8 @@ resolve_variable (gfc_expr *e)
   /* Like above, but for class types, where the checking whether an array
      ref is present is more complicated.  Furthermore make sure not to add
      the full array ref to _vptr or _len refs.  */
-  if (sym->assoc && sym->ts.type == BT_CLASS
+  if (sym->assoc && sym->ts.type == BT_CLASS && sym->ts.u.derived
+      && CLASS_DATA (sym)
       && CLASS_DATA (sym)->attr.dimension
       && (e->ts.type != BT_DERIVED || !e->ts.u.derived->attr.vtype))
     {
@@ -9345,6 +9348,7 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns)
 
       /* Check F03:C815.  */
       if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS)
+         && selector_type
          && !selector_type->attr.unlimited_polymorphic
          && !gfc_type_is_extensible (c->ts.u.derived))
        {
@@ -9355,7 +9359,8 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns)
        }
 
       /* Check F03:C816.  */
-      if (c->ts.type != BT_UNKNOWN && !selector_type->attr.unlimited_polymorphic
+      if (c->ts.type != BT_UNKNOWN
+         && selector_type && !selector_type->attr.unlimited_polymorphic
          && ((c->ts.type != BT_DERIVED && c->ts.type != BT_CLASS)
              || !gfc_type_is_extension_of (selector_type, c->ts.u.derived)))
        {
diff --git a/gcc/testsuite/gfortran.dg/pr102332.f90 b/gcc/testsuite/gfortran.dg/pr102332.f90
new file mode 100644 (file)
index 0000000..f955709
--- /dev/null
@@ -0,0 +1,69 @@
+! { dg-do compile }
+! PR fortran/102332 - ICE in select_type_set_tmp
+! Contributed by G.Steinmetz
+
+program p
+  type t
+     real :: a, b
+  end type
+  class(t), allocatable :: x ! Valid
+  select type (y => x)
+  type is (t)
+     y%a = 0
+  end select
+end
+
+subroutine s0 (x)
+  type t
+     real :: a, b
+  end type
+  class(t) :: x ! Valid
+  select type (y => x)
+  type is (t)
+     y%a = 0
+  end select
+end
+
+subroutine s1
+  type t
+     real :: a, b
+  end type
+  class(t) :: x         ! { dg-error "must be dummy, allocatable or pointer" }
+  select type (y => x)
+  type is (t)
+     y%a = 0
+  end select
+end
+
+subroutine s3
+  type t
+     real :: a, b
+  end type
+  class(t) :: x         ! { dg-error "must be dummy, allocatable or pointer" }
+  select type (y => x)
+  class is (t)
+     y%a = 0
+  end select
+end
+
+subroutine s2
+  type t
+     real :: a, b
+  end type
+  class(t) :: x         ! { dg-error "must be dummy, allocatable or pointer" }
+  select type (y => x)
+  type default          ! { dg-error "Expected" }
+     y%a = 0
+  end select
+end
+
+subroutine s4
+  type t
+     real :: a, b
+  end type
+  class(t) :: x         ! { dg-error "must be dummy, allocatable or pointer" }
+  select type (y => x)
+  class default
+     y%a = 0
+  end select
+end