On 07/12/2016 06:26 AM, Dominique d'Humières wrote: >>> 2016-07-11 Jerry DeLisle <jvdeli...@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 > Please hold on. I still see several problem with the patch applied. One is > > program p > character :: z = 'z' > print *, repeat(z, huge(1)-2**9) > end
Please test this revised patch. See my comments in the PR. I think we should commit this one. Jerry
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 77831ab..dcacae8 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -59,6 +59,8 @@ not after. #define MAX_SUBRECORD_LENGTH 2147483639 /* 2**31-9 */ +/* Practical limit on size of character constants. */ +#define MAX_CHAR_LENGTH 268435455 /* 2**28-1 */ #define gfc_is_whitespace(c) ((c==' ') || (c=='\t')) diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c index 8096a92..4010753 100644 --- a/gcc/fortran/simplify.c +++ b/gcc/fortran/simplify.c @@ -5085,24 +5085,29 @@ 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); i = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false); + /* Set the limit on size to avoid unsigned integer + wrapping and resource limits. */ + mpz_init_set_si (limit, MAX_CHAR_LENGTH); + 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); } + mpz_clear (limit); /* The check itself. */ if (mpz_cmp (ncopies, max) > 0) diff --git a/gcc/testsuite/gfortran.dg/repeat_4.f90 b/gcc/testsuite/gfortran.dg/repeat_4.f90 index e5b5acc..a6ee75b 100644 --- a/gcc/testsuite/gfortran.dg/repeat_4.f90 +++ b/gcc/testsuite/gfortran.dg/repeat_4.f90 @@ -22,17 +22,17 @@ 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(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 " } - print *, repeat(t0, huge(0)/2) - print *, repeat(t1, huge(0)/2) - print *, repeat(t2, huge(0)/2) + print *, repeat(t0, huge(0)/8) + print *, repeat(t1, huge(0)/8) + print *, repeat(t2, huge(0)/16) print *, repeat(t0, huge(0)/2+1) - print *, repeat(t1, huge(0)/2+1) - print *, repeat(t2, huge(0)/2+1) ! { dg-error "Argument NCOPIES of REPEAT intrinsic is too large " } - print *, repeat(s2, huge(0)/2+1) ! { dg-error "Argument NCOPIES of REPEAT intrinsic is too large " } + print *, repeat(t1, huge(0)/8+1) ! { dg-error "Argument NCOPIES of REPEAT intrinsic is too large " } + print *, repeat(t2, huge(0)/16+1)! { dg-error "Argument NCOPIES of REPEAT intrinsic is too large " } + print *, repeat(s2, huge(0)/16+1)! { dg-error "Argument NCOPIES of REPEAT intrinsic is too large " } end program test