This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch, Fortran] PR33745 - fix bound checking at run time (wrong code) and compile time (missing diagnostic)


:ADDPATCH fortran:

Run time:
For assumed-size arrays, the upper limit of the last dimension cannot be
checked as it is unknown. trans-arrays.c's gfc_conv_ss_startstride
contained a check, however, the loop "for (n = 0; n < loop->dimen; n++)"
only checks for ranges and not for elements/vectors. Thus for "j(1,1:2)"
only the second dimension is checked. The variables are then n=0,
loop->dimen=1, however, n=0 denotes the second dimension ("1") and the
maximal dimension is info->ref->u.ar.dimen = 2. Therefore the check
   n == info->ref->u.ar.dimen - 1  /* 0 == (2 - 1) */
was false and the upper bound of the second dimension (= assumed size)
was checked (-> bogus run-time error).  The solution is to use the
absolute dimension "dim" ("dim = info->dim[n]").

Compile time:
Here, the problem is similar. Assume that jp's is defined as "jp(2,*)"
then "jp(3,1:2)" is out of bounds in the first dimension; however,
gfortran did not detect it. In resolve.c's "check_dimension(int i,
....)" (here, "i" is the dimension index) there is a "switch
(ar->type)". ar-type contains the overall type (which is AR_SECTION for
"jp(3,1:2)"); actually, the needed information is the type for the
current dimension, i.e. ar->dimen_type[i].
I fixed that and took also the opportunity to improve the diagnostic output.

Build and regression tested on x86-64/Linux. OK for the trunk?

Tobias
2007-10-13  Tobias Burnus  <burnus@net-b.de>

	PR fortran/33745
	* trans-array.c (gfc_conv_ss_startstride): Fix dimension check.
	* resolve.c (check_dimension): Fix dimension-type switch;
	improve error message.

2007-10-13  Tobias Burnus  <burnus@net-b.de>

	PR fortran/33745
	* gfortran.dg/bounds_check_10.f90: New.


Index: gcc/fortran/trans-array.c
===================================================================
--- gcc/fortran/trans-array.c	(Revision 129284)
+++ gcc/fortran/trans-array.c	(Arbeitskopie)
@@ -2870,7 +2870,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * 
 	      if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
 		continue;
 
-	      if (n == info->ref->u.ar.dimen - 1
+	      if (dim == info->ref->u.ar.dimen - 1
 		  && (info->ref->u.ar.as->type == AS_ASSUMED_SIZE
 		      || info->ref->u.ar.as->cp_was_assumed))
 		check_upper = false;
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c	(Revision 129284)
+++ gcc/fortran/resolve.c	(Arbeitskopie)
@@ -3215,20 +3190,32 @@ check_dimension (int i, gfc_array_ref *a
 /* Given start, end and stride values, calculate the minimum and
    maximum referenced indexes.  */
 
-  switch (ar->type)
+  switch (ar->dimen_type[i])
     {
-    case AR_FULL:
+    case DIMEN_VECTOR:
       break;
 
-    case AR_ELEMENT:
+    case DIMEN_ELEMENT:
       if (compare_bound (ar->start[i], as->lower[i]) == CMP_LT)
-	goto bound;
+	{
+	  gfc_warning ("Array reference at %L is out of bounds "
+		       "(%ld < %ld) in dimension %d", &ar->c_where[i],
+		       mpz_get_si (ar->start[i]->value.integer),
+		       mpz_get_si (as->lower[i]->value.integer), i+1);
+	  return SUCCESS;
+	}
       if (compare_bound (ar->start[i], as->upper[i]) == CMP_GT)
-	goto bound;
+	{
+	  gfc_warning ("Array reference at %L is out of bounds "
+		       "(%ld > %ld) in dimension %d", &ar->c_where[i],
+		       mpz_get_si (ar->start[i]->value.integer),
+		       mpz_get_si (as->upper[i]->value.integer), i+1);
+	  return SUCCESS;
+	}
 
       break;
 
-    case AR_SECTION:
+    case DIMEN_RANGE:
       {
 #define AR_START (ar->start[i] ? ar->start[i] : as->lower[i])
 #define AR_END (ar->end[i] ? ar->end[i] : as->upper[i])
@@ -3253,9 +3240,22 @@ check_dimension (int i, gfc_array_ref *a
 	    || (compare_bound_int (ar->stride[i], 0) == CMP_LT
 	        && comp_start_end == CMP_GT))
 	  {
-	    if (compare_bound (AR_START, as->lower[i]) == CMP_LT
-		|| compare_bound (AR_START, as->upper[i]) == CMP_GT)
-	      goto bound;
+	    if (compare_bound (AR_START, as->lower[i]) == CMP_LT)
+	      {
+		gfc_warning ("Lower array reference at %L is out of bounds "
+		       "(%ld < %ld) in dimension %d", &ar->c_where[i],
+		       mpz_get_si (AR_START->value.integer),
+		       mpz_get_si (as->lower[i]->value.integer), i+1);
+		return SUCCESS;
+	      }
+	    if (compare_bound (AR_START, as->upper[i]) == CMP_GT)
+	      {
+		gfc_warning ("Lower array reference at %L is out of bounds "
+		       "(%ld > %ld) in dimension %d", &ar->c_where[i],
+		       mpz_get_si (AR_START->value.integer),
+		       mpz_get_si (as->upper[i]->value.integer), i+1);
+		return SUCCESS;
+	      }
 	  }
 
 	/* If we can compute the highest index of the array section,
@@ -3264,11 +3264,23 @@ check_dimension (int i, gfc_array_ref *a
 	if (compute_last_value_for_triplet (AR_START, AR_END, ar->stride[i],
 					    last_value))
 	  {
-	    if (compare_bound_mpz_t (as->lower[i], last_value) == CMP_GT
-	        || compare_bound_mpz_t (as->upper[i], last_value) == CMP_LT)
+	    if (compare_bound_mpz_t (as->lower[i], last_value) == CMP_GT)
+	      {
+		gfc_warning ("Upper array reference at %L is out of bounds "
+		       "(%ld < %ld) in dimension %d", &ar->c_where[i],
+		       mpz_get_si (last_value),
+		       mpz_get_si (as->lower[i]->value.integer), i+1);
+	        mpz_clear (last_value);
+		return SUCCESS;
+	      }
+	    if (compare_bound_mpz_t (as->upper[i], last_value) == CMP_LT)
 	      {
+		gfc_warning ("Upper array reference at %L is out of bounds "
+		       "(%ld > %ld) in dimension %d", &ar->c_where[i],
+		       mpz_get_si (last_value),
+		       mpz_get_si (as->upper[i]->value.integer), i+1);
 	        mpz_clear (last_value);
-	        goto bound;
+		return SUCCESS;
 	      }
 	  }
 	mpz_clear (last_value);
@@ -3283,10 +3295,6 @@ check_dimension (int i, gfc_array_ref *a
     }
 
   return SUCCESS;
-
-bound:
-  gfc_warning ("Array reference at %L is out of bounds", &ar->c_where[i]);
-  return SUCCESS;
 }
 
 
Index: gcc/testsuite/gfortran.dg/bounds_check_10.f90
===================================================================
--- gcc/testsuite/gfortran.dg/bounds_check_10.f90	(Revision 0)
+++ gcc/testsuite/gfortran.dg/bounds_check_10.f90	(Revision 0)
@@ -0,0 +1,25 @@
+! { dg-do run }
+! { dg-options "-fbounds-check" }
+! { dg-shouldfail "Array bound checking" }
+! PR fortran/33745
+!
+! Don't check upper bound of assumed-size array
+!
+
+program test
+ implicit none
+ integer, parameter :: maxss=7,maxc=8
+ integer :: jp(2,maxc)
+ call findphase(jp)
+contains
+  subroutine findphase(jp)
+    integer, intent(out) :: jp(2,*)
+    jp(2,2:4)=0
+    jp(2,0:4)=0 ! { dg-warning "out of bounds" }
+    jp(3,1:4)=0 ! { dg-warning "out of bounds" }
+  end subroutine
+end program test
+
+! { dg-output "At line 18 of file .*" }
+! { dg-output "Array reference out of bounds, lower bound of dimension 2 of array 'jp' exceeded, 0 is smaller than 1" }
+

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]