Message ID | 2ea5e1c6-a6cb-f3eb-074d-34584d5e6dfe@charter.net |
---|---|
State | New |
Headers | show |
> 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
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 --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 " }