diff mbox

[fortran] PR66310 Problems with intrinsic repeat for large number of copies

Message ID 2ea5e1c6-a6cb-f3eb-074d-34584d5e6dfe@charter.net
State New
Headers show

Commit Message

Jerry DeLisle July 12, 2016, 12:54 a.m. UTC
Attached patch sets a limit of huge-1 on the character count to avoid the
integer wrap.

Regression tested with adjustment to test case.

OK for trunk?

Regards,

Jerry

2016-07-11  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/66310
	* simplify.c (gfc_simplify_repeat): Set max repeat to huge - 1 to allow
	one byte for null terminating the resulting string constant.

   print *, repeat(s2, huge(0)) ! { dg-error "Argument NCOPIES of REPEAT
intrinsic is too large " }

Comments

FX July 12, 2016, 12:57 p.m. UTC | #1
> 2016-07-11  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
> 
> 	PR fortran/66310
> 	* simplify.c (gfc_simplify_repeat): Set max repeat to huge - 1 to allow
> 	one byte for null terminating the resulting string constant.

OK, thanks
William Clodius July 13, 2016, 1:54 a.m. UTC | #2
A minor question. Why with Fortran’s counted strings are you appending a null character?

> On Jul 11, 2016, at 6:54 PM, Jerry DeLisle <jvdelisle@charter.net> wrote:
> 
> Attached patch sets a limit of huge-1 on the character count to avoid the
> integer wrap.
> 
> Regression tested with adjustment to test case.
> 
> OK for trunk?
> 
> Regards,
> 
> Jerry
> 
> 2016-07-11  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
> 
> 	PR fortran/66310
> 	* simplify.c (gfc_simplify_repeat): Set max repeat to huge - 1 to allow
> 	one byte for null terminating the resulting string constant.
> 
> diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
> index 95a8d10..03257ec 100644
> --- a/gcc/fortran/simplify.c
> +++ b/gcc/fortran/simplify.c
> @@ -5081,22 +5081,27 @@ gfc_simplify_repeat (gfc_expr *e, gfc_expr *n)
>   /* Check that NCOPIES isn't too large.  */
>   if (len)
>     {
> -      mpz_t max, mlen;
> +      mpz_t max, mlen, limit;
>       int i;
> 
> -      /* Compute the maximum value allowed for NCOPIES: huge(cl) / len.  */
> +      /* Compute the maximum value allowed for NCOPIES:
> +           huge(cl) - 1 / len.  */
>       mpz_init (max);
> +      mpz_init (limit);
>       i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
> 
> +      /* Set the limit on size to huge-1 to avoid unsigned integer
> +        wrapping in gfc_get_character_expr.  */
> +      mpz_sub_ui (limit, gfc_integer_kinds[i].huge, 1);
> +
>       if (have_length)
>        {
> -         mpz_tdiv_q (max, gfc_integer_kinds[i].huge,
> -                     e->ts.u.cl->length->value.integer);
> +         mpz_tdiv_q (max, limit, e->ts.u.cl->length->value.integer);
>        }
>       else
>        {
>          mpz_init_set_si (mlen, len);
> -         mpz_tdiv_q (max, gfc_integer_kinds[i].huge, mlen);
> +         mpz_tdiv_q (max, limit, mlen);
>          mpz_clear (mlen);
>        }
> 
> @@ -5104,6 +5109,7 @@ gfc_simplify_repeat (gfc_expr *e, gfc_expr *n)
>       if (mpz_cmp (ncopies, max) > 0)
>        {
>          mpz_clear (max);
> +         mpz_clear (limit);
>          mpz_clear (ncopies);
>          gfc_error ("Argument NCOPIES of REPEAT intrinsic is too large at %L",
>                     &n->where);
> @@ -5111,6 +5117,7 @@ gfc_simplify_repeat (gfc_expr *e, gfc_expr *n)
>        }
> 
>       mpz_clear (max);
> +      mpz_clear (limit);
>     }
>   mpz_clear (ncopies);
> 
> diff --git a/gcc/testsuite/gfortran.dg/repeat_4.f90
> b/gcc/testsuite/gfortran.dg/repeat_4.f90
> index e5b5acc..77483a1 100644
> --- a/gcc/testsuite/gfortran.dg/repeat_4.f90
> +++ b/gcc/testsuite/gfortran.dg/repeat_4.f90
> @@ -22,7 +22,8 @@ program test
> 
>   ! Check for too large NCOPIES argument and limit cases
>   print *, repeat(t0, huge(0))
> -  print *, repeat(t1, huge(0))
> +  print *, repeat(t1, huge(0)) ! { dg-error "Argument NCOPIES of REPEAT
> intrinsic is too large " }
> +  print *, repeat(t1, huge(0) - 1)
>   print *, repeat(t2, huge(0)) ! { dg-error "Argument NCOPIES of REPEAT
> intrinsic is too large " }
>   print *, repeat(s2, huge(0)) ! { dg-error "Argument NCOPIES of REPEAT
> intrinsic is too large " }
>
diff mbox

Patch

diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 95a8d10..03257ec 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -5081,22 +5081,27 @@  gfc_simplify_repeat (gfc_expr *e, gfc_expr *n)
   /* Check that NCOPIES isn't too large.  */
   if (len)
     {
-      mpz_t max, mlen;
+      mpz_t max, mlen, limit;
       int i;

-      /* Compute the maximum value allowed for NCOPIES: huge(cl) / len.  */
+      /* Compute the maximum value allowed for NCOPIES:
+           huge(cl) - 1 / len.  */
       mpz_init (max);
+      mpz_init (limit);
       i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);

+      /* Set the limit on size to huge-1 to avoid unsigned integer
+        wrapping in gfc_get_character_expr.  */
+      mpz_sub_ui (limit, gfc_integer_kinds[i].huge, 1);
+
       if (have_length)
        {
-         mpz_tdiv_q (max, gfc_integer_kinds[i].huge,
-                     e->ts.u.cl->length->value.integer);
+         mpz_tdiv_q (max, limit, e->ts.u.cl->length->value.integer);
        }
       else
        {
          mpz_init_set_si (mlen, len);
-         mpz_tdiv_q (max, gfc_integer_kinds[i].huge, mlen);
+         mpz_tdiv_q (max, limit, mlen);
          mpz_clear (mlen);
        }

@@ -5104,6 +5109,7 @@  gfc_simplify_repeat (gfc_expr *e, gfc_expr *n)
       if (mpz_cmp (ncopies, max) > 0)
        {
          mpz_clear (max);
+         mpz_clear (limit);
          mpz_clear (ncopies);
          gfc_error ("Argument NCOPIES of REPEAT intrinsic is too large at %L",
                     &n->where);
@@ -5111,6 +5117,7 @@  gfc_simplify_repeat (gfc_expr *e, gfc_expr *n)
        }

       mpz_clear (max);
+      mpz_clear (limit);
     }
   mpz_clear (ncopies);

diff --git a/gcc/testsuite/gfortran.dg/repeat_4.f90
b/gcc/testsuite/gfortran.dg/repeat_4.f90
index e5b5acc..77483a1 100644
--- a/gcc/testsuite/gfortran.dg/repeat_4.f90
+++ b/gcc/testsuite/gfortran.dg/repeat_4.f90
@@ -22,7 +22,8 @@  program test

   ! Check for too large NCOPIES argument and limit cases
   print *, repeat(t0, huge(0))
-  print *, repeat(t1, huge(0))
+  print *, repeat(t1, huge(0)) ! { dg-error "Argument NCOPIES of REPEAT
intrinsic is too large " }
+  print *, repeat(t1, huge(0) - 1)
   print *, repeat(t2, huge(0)) ! { dg-error "Argument NCOPIES of REPEAT
intrinsic is too large " }