From: Harald Anlauf Date: Mon, 27 Dec 2021 22:06:18 +0000 (+0100) Subject: Fortran: avoid several NULL pointer dereferences during error recovery X-Git-Tag: releases/gcc-10.4.0~478 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7bfdbb657919b5049e459e02d130056cfe3777b6;p=thirdparty%2Fgcc.git Fortran: avoid several NULL pointer dereferences during error recovery 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) --- diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c index 95b351539419..e8c7c212e708 100644 --- a/gcc/fortran/expr.c +++ b/gcc/fortran/expr.c @@ -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 diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c index ef6c86af2f95..7d06e0eef30c 100644 --- a/gcc/fortran/match.c +++ b/gcc/fortran/match.c @@ -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; diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c index b03961a99816..78c4b634db33 100644 --- a/gcc/fortran/primary.c +++ b/gcc/fortran/primary.c @@ -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))) { diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 591b36fa4bd9..9104b17988b7 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -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 index 000000000000..f95570940834 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr102332.f90 @@ -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