Harald, I did a quick glance at the patch and did not see anything that jumped out as needing a change. OK to commit.
Earlier today I came to the same conclusion that -1 on overflow is probably the right thing to do. Gfortran would need a way to supply the value of ERANGE (on all supported targets) so a user can write a test. Yes, POSIX seems to define ERANGE as 34, but is that guaranteed on non-POSIX targets? -- steve On Sun, Jun 15, 2025 at 09:01:37PM +0200, Harald Anlauf wrote: > > here's a modification that returns -1 for those components of stat > that would overflow assignment to integer(kind=4), and does not > return ERANGE as in v1 of this patch. There is no need to modify > the existing testcasese stat_{1,2}.f90. > > Cheers, > Harald > > Am 12.06.25 um 22:12 schrieb Harald Anlauf: > > Hi Steve, > > > > On 6/11/25 23:06, Steve Kargl wrote: > > > On Wed, Jun 11, 2025 at 10:18:37PM +0200, Harald Anlauf wrote: > > > > - for the INTEGER(KIND=4) versions the STATUS returns ERANGE if > > > > an overflow is encountered. > > > > > > > > The latter is certainly debatable, as one of the existing testcases > > > > stat_{1,2}.f90 may fail on systems where e.g. an inode number is larger > > > > than INT32_MAX may occur. Options are to drop the overflow check, or > > > > to run those testcases with additional option -fdefault-integer-8. > > > > > > > > Opinions? > > > > > > > > another option is: > > > > - return -1 for components which overflow, and not return ERANGE, > > thus to leave it up to the user to handle this > > > > It is arguably not an error generated by stat(3), but by the > > interface to Fortran in the runtime. > > > > > > > > Thanks for doing these types of cleanups. > > > > > > You may want to take a peek at > > > > > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30372 > > > > > > where I posted a few cleanups for SLEEP, UMASK, UNLINK, > > > etc. In those cleanups, I would cast arguments to > > > integer(4) if I could (ie., if I know the arg was in range) > > > to prevent an explosion in the size of libgfortran. > > > > I do not plan to implement any new library versions. The > > *_i4 and *_i8 versions are already available. All integer > > arguments should be kind=4 or 8, and needed conversions > > can be done using scalar temporaries. > > > > > I'll need to think about your -fdefault-integer-8 question > > > for a bit. Because that option exists and can change > > > default integer kind, we'll need *_i4 and *_i8 versions of > > > the functions in libgfortran. I suspect we'll need to > > > run the testcases with -fdefault-integer-8. > > > > This depends on the way we handle overflow. The variant > > above would not need this option. > > > > > If no one approves your patch by Saturday, I'll review. > > > > Any helpful feedback is greatly appreciated. > > > > Thanks > > Harald > > > > > > > From aa79324885ba44b64911ec7a75375b28a2223cf7 Mon Sep 17 00:00:00 2001 > From: Harald Anlauf <anl...@gmx.de> > Date: Sun, 15 Jun 2025 20:47:13 +0200 > Subject: [PATCH] Fortran: various fixes for STAT/LSTAT/FSTAT intrinsics > [PR82480] > > The GNU intrinsics STAT/LSTAT/FSTAT were inherited from g77, but changed > the names of some keywords: FILE became NAME, and SARRAY became VALUES, > which are the keywords documented in the gfortran manual. > Adjust code and libgfortran error messages to reflect this change. > Furthermore, add compile-time checking that INTENT(OUT) arguments are > definable, and that array VALUES has at least size 13. > > PR fortran/82480 > > gcc/fortran/ChangeLog: > > * check.cc (gfc_check_fstat): Extend checks to INTENT(OUT) arguments. > (gfc_check_fstat_sub): Likewise. > (gfc_check_stat): Likewise. > (gfc_check_stat_sub): Likewise. > > libgfortran/ChangeLog: > > * intrinsics/stat.c (stat_i4_sub_0): Fix argument names. Rename > SARRAY to VALUES also in error message. When array VALUES is > KIND=4, get only stat components that do not overflow INT32_MAX, > otherwise set the corresponding VALUES elements to -1. > (stat_i4_sub): Fix argument names. > (lstat_i4_sub): Likewise. > (stat_i8_sub_0): Likewise. > (stat_i8_sub): Likewise. > (lstat_i8_sub): Likewise. > (stat_i4): Likewise. > (stat_i8): Likewise. > (lstat_i4): Likewise. > (lstat_i8): Likewise. > (fstat_i4_sub): Likewise. > (fstat_i8_sub): Likewise. > (fstat_i4): Likewise. > (fstat_i8): Likewise. > > gcc/testsuite/ChangeLog: > > * gfortran.dg/stat_3.f90: New test. > --- > gcc/fortran/check.cc | 61 +++--- > gcc/testsuite/gfortran.dg/stat_3.f90 | 46 +++++ > libgfortran/intrinsics/stat.c | 274 +++++++++++++++------------ > 3 files changed, 226 insertions(+), 155 deletions(-) > create mode 100644 gcc/testsuite/gfortran.dg/stat_3.f90 > > diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc > index c8904df3b21..838d523f7c4 100644 > --- a/gcc/fortran/check.cc > +++ b/gcc/fortran/check.cc > @@ -6507,7 +6507,7 @@ gfc_check_fseek_sub (gfc_expr *unit, gfc_expr *offset, > gfc_expr *whence, gfc_exp > > > bool > -gfc_check_fstat (gfc_expr *unit, gfc_expr *array) > +gfc_check_fstat (gfc_expr *unit, gfc_expr *values) > { > if (!type_check (unit, 0, BT_INTEGER)) > return false; > @@ -6515,11 +6515,17 @@ gfc_check_fstat (gfc_expr *unit, gfc_expr *array) > if (!scalar_check (unit, 0)) > return false; > > - if (!type_check (array, 1, BT_INTEGER) > + if (!type_check (values, 1, BT_INTEGER) > || !kind_value_check (unit, 0, gfc_default_integer_kind)) > return false; > > - if (!array_check (array, 1)) > + if (!array_check (values, 1)) > + return false; > + > + if (!variable_check (values, 1, false)) > + return false; > + > + if (!array_size_check (values, 1, 13)) > return false; > > return true; > @@ -6527,19 +6533,9 @@ gfc_check_fstat (gfc_expr *unit, gfc_expr *array) > > > bool > -gfc_check_fstat_sub (gfc_expr *unit, gfc_expr *array, gfc_expr *status) > +gfc_check_fstat_sub (gfc_expr *unit, gfc_expr *values, gfc_expr *status) > { > - if (!type_check (unit, 0, BT_INTEGER)) > - return false; > - > - if (!scalar_check (unit, 0)) > - return false; > - > - if (!type_check (array, 1, BT_INTEGER) > - || !kind_value_check (array, 1, gfc_default_integer_kind)) > - return false; > - > - if (!array_check (array, 1)) > + if (!gfc_check_fstat (unit, values)) > return false; > > if (status == NULL) > @@ -6552,6 +6548,9 @@ gfc_check_fstat_sub (gfc_expr *unit, gfc_expr *array, > gfc_expr *status) > if (!scalar_check (status, 2)) > return false; > > + if (!variable_check (status, 2, false)) > + return false; > + > return true; > } > > @@ -6589,18 +6588,24 @@ gfc_check_ftell_sub (gfc_expr *unit, gfc_expr *offset) > > > bool > -gfc_check_stat (gfc_expr *name, gfc_expr *array) > +gfc_check_stat (gfc_expr *name, gfc_expr *values) > { > if (!type_check (name, 0, BT_CHARACTER)) > return false; > if (!kind_value_check (name, 0, gfc_default_character_kind)) > return false; > > - if (!type_check (array, 1, BT_INTEGER) > - || !kind_value_check (array, 1, gfc_default_integer_kind)) > + if (!type_check (values, 1, BT_INTEGER) > + || !kind_value_check (values, 1, gfc_default_integer_kind)) > return false; > > - if (!array_check (array, 1)) > + if (!array_check (values, 1)) > + return false; > + > + if (!variable_check (values, 1, false)) > + return false; > + > + if (!array_size_check (values, 1, 13)) > return false; > > return true; > @@ -6608,30 +6613,24 @@ gfc_check_stat (gfc_expr *name, gfc_expr *array) > > > bool > -gfc_check_stat_sub (gfc_expr *name, gfc_expr *array, gfc_expr *status) > +gfc_check_stat_sub (gfc_expr *name, gfc_expr *values, gfc_expr *status) > { > - if (!type_check (name, 0, BT_CHARACTER)) > - return false; > - if (!kind_value_check (name, 0, gfc_default_character_kind)) > - return false; > - > - if (!type_check (array, 1, BT_INTEGER) > - || !kind_value_check (array, 1, gfc_default_integer_kind)) > - return false; > - > - if (!array_check (array, 1)) > + if (!gfc_check_stat (name, values)) > return false; > > if (status == NULL) > return true; > > if (!type_check (status, 2, BT_INTEGER) > - || !kind_value_check (array, 1, gfc_default_integer_kind)) > + || !kind_value_check (status, 2, gfc_default_integer_kind)) > return false; > > if (!scalar_check (status, 2)) > return false; > > + if (!variable_check (status, 2, false)) > + return false; > + > return true; > } > > diff --git a/gcc/testsuite/gfortran.dg/stat_3.f90 > b/gcc/testsuite/gfortran.dg/stat_3.f90 > new file mode 100644 > index 00000000000..93ec1836a9a > --- /dev/null > +++ b/gcc/testsuite/gfortran.dg/stat_3.f90 > @@ -0,0 +1,46 @@ > +! { dg-do compile } > +! PR fortran/82480 - checking of arguments to STAT/LSTAT/FSTAT > + > +subroutine sub1 () > + integer, parameter :: ik = kind(1) > + integer(ik) :: buff12(12) > + integer(ik) :: buff13(13) > + integer(ik) :: unit = 10 > + integer(ik) :: ierr > + character(len=64) :: name = "/etc/passwd" > + ierr = stat (name, values= buff12) ! { dg-error "too small" } > + ierr = stat (name, values= buff13) > + ierr = lstat (name, values= buff12) ! { dg-error "too small" } > + ierr = lstat (name, values= buff13) > + ierr = fstat (unit, values= buff12) ! { dg-error "too small" } > + ierr = fstat (unit, values= buff13) > + ierr = stat (name, values=(buff13)) ! { dg-error "must be a variable" } > + ierr = lstat (name, values=(buff13)) ! { dg-error "must be a variable" } > + ierr = fstat (unit, values=(buff13)) ! { dg-error "must be a variable" } > +end > + > +subroutine sub2 () > + integer, parameter :: ik = kind(1) > + integer(ik) :: buff12(12) > + integer(ik), target :: buff13(13) = 0 > + integer(ik) :: unit = 10 > + integer(ik), target :: ierr = 0 > + character(len=64) :: name = "/etc/passwd" > + integer(ik),pointer :: pbuf(:) => buff13 > + integer(ik),pointer :: perr => ierr > + call stat (name, status=ierr, values= buff12) ! { dg-error "too small" } > + call stat (name, status=ierr, values= buff13) > + call lstat (name, status=ierr, values= buff12) ! { dg-error "too small" } > + call lstat (name, status=ierr, values= buff13) > + call fstat (unit, status=ierr, values= buff12) ! { dg-error "too small" } > + call fstat (unit, status=ierr, values= buff13) > + call stat (name, status=ierr, values=(buff13)) ! { dg-error "must be a > variable" } > + call lstat (name, status=ierr, values=(buff13)) ! { dg-error "must be a > variable" } > + call fstat (unit, status=ierr, values=(buff13)) ! { dg-error "must be a > variable" } > + call stat (name, status=(ierr),values=buff13) ! { dg-error "must be a > variable" } > + call lstat (name, status=(ierr),values=buff13) ! { dg-error "must be a > variable" } > + call fstat (unit, status=(ierr),values=buff13) ! { dg-error "must be a > variable" } > + call stat (name, status=perr, values= pbuf) > + call lstat (name, status=perr, values= pbuf) > + call fstat (unit, status=perr, values= pbuf) > +end > diff --git a/libgfortran/intrinsics/stat.c b/libgfortran/intrinsics/stat.c > index 8d32f223b24..63a57cd05ee 100644 > --- a/libgfortran/intrinsics/stat.c > +++ b/libgfortran/intrinsics/stat.c > @@ -35,22 +35,22 @@ see the files COPYING3 and COPYING.RUNTIME respectively. > If not, see > > #ifdef HAVE_STAT > > -/* SUBROUTINE STAT(FILE, SARRAY, STATUS) > +/* SUBROUTINE STAT(NAME, VALUES, STATUS) > CHARACTER(len=*), INTENT(IN) :: FILE > - INTEGER, INTENT(OUT), :: SARRAY(13) > + INTEGER, INTENT(OUT), :: VALUES(13) > INTEGER, INTENT(OUT), OPTIONAL :: STATUS > > - FUNCTION STAT(FILE, SARRAY) > + FUNCTION STAT(NAME, VALUES) > INTEGER STAT > CHARACTER(len=*), INTENT(IN) :: FILE > - INTEGER, INTENT(OUT), :: SARRAY(13) */ > + INTEGER, INTENT(OUT), :: VALUES(13) */ > > /*extern void stat_i4_sub_0 (char *, gfc_array_i4 *, GFC_INTEGER_4 *, > gfc_charlen_type, int); > internal_proto(stat_i4_sub_0);*/ > > static void > -stat_i4_sub_0 (char *name, gfc_array_i4 *sarray, GFC_INTEGER_4 *status, > +stat_i4_sub_0 (char *name, gfc_array_i4 *values, GFC_INTEGER_4 *status, > gfc_charlen_type name_len, int is_lstat __attribute__ ((unused))) > { > int val; > @@ -58,12 +58,12 @@ stat_i4_sub_0 (char *name, gfc_array_i4 *sarray, > GFC_INTEGER_4 *status, > struct stat sb; > > /* If the rank of the array is not 1, abort. */ > - if (GFC_DESCRIPTOR_RANK (sarray) != 1) > - runtime_error ("Array rank of SARRAY is not 1."); > + if (GFC_DESCRIPTOR_RANK (values) != 1) > + runtime_error ("Array rank of VALUES is not 1."); > > /* If the array is too small, abort. */ > - if (GFC_DESCRIPTOR_EXTENT(sarray,0) < 13) > - runtime_error ("Array size of SARRAY is too small."); > + if (GFC_DESCRIPTOR_EXTENT(values,0) < 13) > + runtime_error ("Array size of VALUES is too small."); > > /* Make a null terminated copy of the string. */ > str = fc_strdup (name, name_len); > @@ -80,57 +80,70 @@ stat_i4_sub_0 (char *name, gfc_array_i4 *sarray, > GFC_INTEGER_4 *status, > > if (val == 0) > { > - index_type stride = GFC_DESCRIPTOR_STRIDE(sarray,0); > + index_type stride = GFC_DESCRIPTOR_STRIDE(values,0); > + > + /* Return -1 for any value overflowing INT32_MAX. */ > + for (int i = 0; i < 13; i++) > + values->base_addr[i * stride] = -1; > > /* Device ID */ > - sarray->base_addr[0 * stride] = sb.st_dev; > + if (sb.st_dev <= INT32_MAX) > + values->base_addr[0 * stride] = sb.st_dev; > > /* Inode number */ > - sarray->base_addr[1 * stride] = sb.st_ino; > + if (sb.st_ino <= INT32_MAX) > + values->base_addr[1 * stride] = sb.st_ino; > > /* File mode */ > - sarray->base_addr[2 * stride] = sb.st_mode; > + if (sb.st_mode <= INT32_MAX) > + values->base_addr[2 * stride] = sb.st_mode; > > /* Number of (hard) links */ > - sarray->base_addr[3 * stride] = sb.st_nlink; > + if (sb.st_nlink <= INT32_MAX) > + values->base_addr[3 * stride] = sb.st_nlink; > > /* Owner's uid */ > - sarray->base_addr[4 * stride] = sb.st_uid; > + if (sb.st_uid <= INT32_MAX) > + values->base_addr[4 * stride] = sb.st_uid; > > /* Owner's gid */ > - sarray->base_addr[5 * stride] = sb.st_gid; > + if (sb.st_gid <= INT32_MAX) > + values->base_addr[5 * stride] = sb.st_gid; > > /* ID of device containing directory entry for file (0 if not > available) */ > #if HAVE_STRUCT_STAT_ST_RDEV > - sarray->base_addr[6 * stride] = sb.st_rdev; > + if (sb.st_rdev <= INT32_MAX) > + values->base_addr[6 * stride] = sb.st_rdev; > #else > - sarray->base_addr[6 * stride] = 0; > + values->base_addr[6 * stride] = 0; > #endif > > /* File size (bytes) */ > - sarray->base_addr[7 * stride] = sb.st_size; > + if (sb.st_size <= INT32_MAX) > + values->base_addr[7 * stride] = sb.st_size; > > /* Last access time */ > - sarray->base_addr[8 * stride] = sb.st_atime; > + if (sb.st_atime <= INT32_MAX) > + values->base_addr[8 * stride] = sb.st_atime; > > /* Last modification time */ > - sarray->base_addr[9 * stride] = sb.st_mtime; > + if (sb.st_mtime <= INT32_MAX) > + values->base_addr[9 * stride] = sb.st_mtime; > > /* Last file status change time */ > - sarray->base_addr[10 * stride] = sb.st_ctime; > + if (sb.st_ctime <= INT32_MAX) > + values->base_addr[10 * stride] = sb.st_ctime; > > /* Preferred I/O block size (-1 if not available) */ > #if HAVE_STRUCT_STAT_ST_BLKSIZE > - sarray->base_addr[11 * stride] = sb.st_blksize; > -#else > - sarray->base_addr[11 * stride] = -1; > + if (sb.st_blksize <= INT32_MAX) > + values->base_addr[11 * stride] = sb.st_blksize; > #endif > > /* Number of blocks allocated (-1 if not available) */ > #if HAVE_STRUCT_STAT_ST_BLOCKS > - sarray->base_addr[12 * stride] = sb.st_blocks; > -#else > - sarray->base_addr[12 * stride] = -1; > + if (sb.st_blocks <= INT32_MAX) > + values->base_addr[12 * stride] = sb.st_blocks; > #endif > } > > @@ -144,10 +157,10 @@ extern void stat_i4_sub (char *, gfc_array_i4 *, > GFC_INTEGER_4 *, > iexport_proto(stat_i4_sub); > > void > -stat_i4_sub (char *name, gfc_array_i4 *sarray, GFC_INTEGER_4 *status, > +stat_i4_sub (char *name, gfc_array_i4 *values, GFC_INTEGER_4 *status, > gfc_charlen_type name_len) > { > - stat_i4_sub_0 (name, sarray, status, name_len, 0); > + stat_i4_sub_0 (name, values, status, name_len, 0); > } > iexport(stat_i4_sub); > > @@ -157,17 +170,17 @@ extern void lstat_i4_sub (char *, gfc_array_i4 *, > GFC_INTEGER_4 *, > iexport_proto(lstat_i4_sub); > > void > -lstat_i4_sub (char *name, gfc_array_i4 *sarray, GFC_INTEGER_4 *status, > +lstat_i4_sub (char *name, gfc_array_i4 *values, GFC_INTEGER_4 *status, > gfc_charlen_type name_len) > { > - stat_i4_sub_0 (name, sarray, status, name_len, 1); > + stat_i4_sub_0 (name, values, status, name_len, 1); > } > iexport(lstat_i4_sub); > > > > static void > -stat_i8_sub_0 (char *name, gfc_array_i8 *sarray, GFC_INTEGER_8 *status, > +stat_i8_sub_0 (char *name, gfc_array_i8 *values, GFC_INTEGER_8 *status, > gfc_charlen_type name_len, int is_lstat __attribute__ ((unused))) > { > int val; > @@ -175,12 +188,12 @@ stat_i8_sub_0 (char *name, gfc_array_i8 *sarray, > GFC_INTEGER_8 *status, > struct stat sb; > > /* If the rank of the array is not 1, abort. */ > - if (GFC_DESCRIPTOR_RANK (sarray) != 1) > - runtime_error ("Array rank of SARRAY is not 1."); > + if (GFC_DESCRIPTOR_RANK (values) != 1) > + runtime_error ("Array rank of VALUES is not 1."); > > /* If the array is too small, abort. */ > - if (GFC_DESCRIPTOR_EXTENT(sarray,0) < 13) > - runtime_error ("Array size of SARRAY is too small."); > + if (GFC_DESCRIPTOR_EXTENT(values,0) < 13) > + runtime_error ("Array size of VALUES is too small."); > > /* Make a null terminated copy of the string. */ > str = fc_strdup (name, name_len); > @@ -197,57 +210,57 @@ stat_i8_sub_0 (char *name, gfc_array_i8 *sarray, > GFC_INTEGER_8 *status, > > if (val == 0) > { > - index_type stride = GFC_DESCRIPTOR_STRIDE(sarray,0); > + index_type stride = GFC_DESCRIPTOR_STRIDE(values,0); > > /* Device ID */ > - sarray->base_addr[0] = sb.st_dev; > + values->base_addr[0] = sb.st_dev; > > /* Inode number */ > - sarray->base_addr[stride] = sb.st_ino; > + values->base_addr[stride] = sb.st_ino; > > /* File mode */ > - sarray->base_addr[2 * stride] = sb.st_mode; > + values->base_addr[2 * stride] = sb.st_mode; > > /* Number of (hard) links */ > - sarray->base_addr[3 * stride] = sb.st_nlink; > + values->base_addr[3 * stride] = sb.st_nlink; > > /* Owner's uid */ > - sarray->base_addr[4 * stride] = sb.st_uid; > + values->base_addr[4 * stride] = sb.st_uid; > > /* Owner's gid */ > - sarray->base_addr[5 * stride] = sb.st_gid; > + values->base_addr[5 * stride] = sb.st_gid; > > /* ID of device containing directory entry for file (0 if not > available) */ > #if HAVE_STRUCT_STAT_ST_RDEV > - sarray->base_addr[6 * stride] = sb.st_rdev; > + values->base_addr[6 * stride] = sb.st_rdev; > #else > - sarray->base_addr[6 * stride] = 0; > + values->base_addr[6 * stride] = 0; > #endif > > /* File size (bytes) */ > - sarray->base_addr[7 * stride] = sb.st_size; > + values->base_addr[7 * stride] = sb.st_size; > > /* Last access time */ > - sarray->base_addr[8 * stride] = sb.st_atime; > + values->base_addr[8 * stride] = sb.st_atime; > > /* Last modification time */ > - sarray->base_addr[9 * stride] = sb.st_mtime; > + values->base_addr[9 * stride] = sb.st_mtime; > > /* Last file status change time */ > - sarray->base_addr[10 * stride] = sb.st_ctime; > + values->base_addr[10 * stride] = sb.st_ctime; > > /* Preferred I/O block size (-1 if not available) */ > #if HAVE_STRUCT_STAT_ST_BLKSIZE > - sarray->base_addr[11 * stride] = sb.st_blksize; > + values->base_addr[11 * stride] = sb.st_blksize; > #else > - sarray->base_addr[11 * stride] = -1; > + values->base_addr[11 * stride] = -1; > #endif > > /* Number of blocks allocated (-1 if not available) */ > #if HAVE_STRUCT_STAT_ST_BLOCKS > - sarray->base_addr[12 * stride] = sb.st_blocks; > + values->base_addr[12 * stride] = sb.st_blocks; > #else > - sarray->base_addr[12 * stride] = -1; > + values->base_addr[12 * stride] = -1; > #endif > } > > @@ -261,10 +274,10 @@ extern void stat_i8_sub (char *, gfc_array_i8 *, > GFC_INTEGER_8 *, > iexport_proto(stat_i8_sub); > > void > -stat_i8_sub (char *name, gfc_array_i8 *sarray, GFC_INTEGER_8 *status, > +stat_i8_sub (char *name, gfc_array_i8 *values, GFC_INTEGER_8 *status, > gfc_charlen_type name_len) > { > - stat_i8_sub_0 (name, sarray, status, name_len, 0); > + stat_i8_sub_0 (name, values, status, name_len, 0); > } > > iexport(stat_i8_sub); > @@ -275,10 +288,10 @@ extern void lstat_i8_sub (char *, gfc_array_i8 *, > GFC_INTEGER_8 *, > iexport_proto(lstat_i8_sub); > > void > -lstat_i8_sub (char *name, gfc_array_i8 *sarray, GFC_INTEGER_8 *status, > +lstat_i8_sub (char *name, gfc_array_i8 *values, GFC_INTEGER_8 *status, > gfc_charlen_type name_len) > { > - stat_i8_sub_0 (name, sarray, status, name_len, 1); > + stat_i8_sub_0 (name, values, status, name_len, 1); > } > > iexport(lstat_i8_sub); > @@ -288,10 +301,10 @@ extern GFC_INTEGER_4 stat_i4 (char *, gfc_array_i4 *, > gfc_charlen_type); > export_proto(stat_i4); > > GFC_INTEGER_4 > -stat_i4 (char *name, gfc_array_i4 *sarray, gfc_charlen_type name_len) > +stat_i4 (char *name, gfc_array_i4 *values, gfc_charlen_type name_len) > { > GFC_INTEGER_4 val; > - stat_i4_sub (name, sarray, &val, name_len); > + stat_i4_sub (name, values, &val, name_len); > return val; > } > > @@ -299,32 +312,32 @@ extern GFC_INTEGER_8 stat_i8 (char *, gfc_array_i8 *, > gfc_charlen_type); > export_proto(stat_i8); > > GFC_INTEGER_8 > -stat_i8 (char *name, gfc_array_i8 *sarray, gfc_charlen_type name_len) > +stat_i8 (char *name, gfc_array_i8 *values, gfc_charlen_type name_len) > { > GFC_INTEGER_8 val; > - stat_i8_sub (name, sarray, &val, name_len); > + stat_i8_sub (name, values, &val, name_len); > return val; > } > > > -/* SUBROUTINE LSTAT(FILE, SARRAY, STATUS) > +/* SUBROUTINE LSTAT(NAME, VALUES, STATUS) > CHARACTER(len=*), INTENT(IN) :: FILE > - INTEGER, INTENT(OUT), :: SARRAY(13) > + INTEGER, INTENT(OUT), :: VALUES(13) > INTEGER, INTENT(OUT), OPTIONAL :: STATUS > > - FUNCTION LSTAT(FILE, SARRAY) > + FUNCTION LSTAT(NAME, VALUES) > INTEGER LSTAT > CHARACTER(len=*), INTENT(IN) :: FILE > - INTEGER, INTENT(OUT), :: SARRAY(13) */ > + INTEGER, INTENT(OUT), :: VALUES(13) */ > > extern GFC_INTEGER_4 lstat_i4 (char *, gfc_array_i4 *, gfc_charlen_type); > export_proto(lstat_i4); > > GFC_INTEGER_4 > -lstat_i4 (char *name, gfc_array_i4 *sarray, gfc_charlen_type name_len) > +lstat_i4 (char *name, gfc_array_i4 *values, gfc_charlen_type name_len) > { > GFC_INTEGER_4 val; > - lstat_i4_sub (name, sarray, &val, name_len); > + lstat_i4_sub (name, values, &val, name_len); > return val; > } > > @@ -332,10 +345,10 @@ extern GFC_INTEGER_8 lstat_i8 (char *, gfc_array_i8 *, > gfc_charlen_type); > export_proto(lstat_i8); > > GFC_INTEGER_8 > -lstat_i8 (char *name, gfc_array_i8 *sarray, gfc_charlen_type name_len) > +lstat_i8 (char *name, gfc_array_i8 *values, gfc_charlen_type name_len) > { > GFC_INTEGER_8 val; > - lstat_i8_sub (name, sarray, &val, name_len); > + lstat_i8_sub (name, values, &val, name_len); > return val; > } > > @@ -344,32 +357,32 @@ lstat_i8 (char *name, gfc_array_i8 *sarray, > gfc_charlen_type name_len) > > #ifdef HAVE_FSTAT > > -/* SUBROUTINE FSTAT(UNIT, SARRAY, STATUS) > +/* SUBROUTINE FSTAT(UNIT, VALUES, STATUS) > INTEGER, INTENT(IN) :: UNIT > - INTEGER, INTENT(OUT) :: SARRAY(13) > + INTEGER, INTENT(OUT) :: VALUES(13) > INTEGER, INTENT(OUT), OPTIONAL :: STATUS > > - FUNCTION FSTAT(UNIT, SARRAY) > + FUNCTION FSTAT(UNIT, VALUES) > INTEGER FSTAT > INTEGER, INTENT(IN) :: UNIT > - INTEGER, INTENT(OUT) :: SARRAY(13) */ > + INTEGER, INTENT(OUT) :: VALUES(13) */ > > extern void fstat_i4_sub (GFC_INTEGER_4 *, gfc_array_i4 *, GFC_INTEGER_4 *); > iexport_proto(fstat_i4_sub); > > void > -fstat_i4_sub (GFC_INTEGER_4 *unit, gfc_array_i4 *sarray, GFC_INTEGER_4 > *status) > +fstat_i4_sub (GFC_INTEGER_4 *unit, gfc_array_i4 *values, GFC_INTEGER_4 > *status) > { > int val; > struct stat sb; > > /* If the rank of the array is not 1, abort. */ > - if (GFC_DESCRIPTOR_RANK (sarray) != 1) > - runtime_error ("Array rank of SARRAY is not 1."); > + if (GFC_DESCRIPTOR_RANK (values) != 1) > + runtime_error ("Array rank of VALUES is not 1."); > > /* If the array is too small, abort. */ > - if (GFC_DESCRIPTOR_EXTENT(sarray,0) < 13) > - runtime_error ("Array size of SARRAY is too small."); > + if (GFC_DESCRIPTOR_EXTENT(values,0) < 13) > + runtime_error ("Array size of VALUES is too small."); > > /* Convert Fortran unit number to C file descriptor. */ > val = unit_to_fd (*unit); > @@ -378,57 +391,70 @@ fstat_i4_sub (GFC_INTEGER_4 *unit, gfc_array_i4 > *sarray, GFC_INTEGER_4 *status) > > if (val == 0) > { > - index_type stride = GFC_DESCRIPTOR_STRIDE(sarray,0); > + index_type stride = GFC_DESCRIPTOR_STRIDE(values,0); > + > + /* Return -1 for any value overflowing INT32_MAX. */ > + for (int i = 0; i < 13; i++) > + values->base_addr[i * stride] = -1; > > /* Device ID */ > - sarray->base_addr[0 * stride] = sb.st_dev; > + if (sb.st_dev <= INT32_MAX) > + values->base_addr[0 * stride] = sb.st_dev; > > /* Inode number */ > - sarray->base_addr[1 * stride] = sb.st_ino; > + if (sb.st_ino <= INT32_MAX) > + values->base_addr[1 * stride] = sb.st_ino; > > /* File mode */ > - sarray->base_addr[2 * stride] = sb.st_mode; > + if (sb.st_mode <= INT32_MAX) > + values->base_addr[2 * stride] = sb.st_mode; > > /* Number of (hard) links */ > - sarray->base_addr[3 * stride] = sb.st_nlink; > + if (sb.st_nlink <= INT32_MAX) > + values->base_addr[3 * stride] = sb.st_nlink; > > /* Owner's uid */ > - sarray->base_addr[4 * stride] = sb.st_uid; > + if (sb.st_uid <= INT32_MAX) > + values->base_addr[4 * stride] = sb.st_uid; > > /* Owner's gid */ > - sarray->base_addr[5 * stride] = sb.st_gid; > + if (sb.st_gid <= INT32_MAX) > + values->base_addr[5 * stride] = sb.st_gid; > > /* ID of device containing directory entry for file (0 if not > available) */ > #if HAVE_STRUCT_STAT_ST_RDEV > - sarray->base_addr[6 * stride] = sb.st_rdev; > + if (sb.st_rdev <= INT32_MAX) > + values->base_addr[6 * stride] = sb.st_rdev; > #else > - sarray->base_addr[6 * stride] = 0; > + values->base_addr[6 * stride] = 0; > #endif > > /* File size (bytes) */ > - sarray->base_addr[7 * stride] = sb.st_size; > + if (sb.st_size <= INT32_MAX) > + values->base_addr[7 * stride] = sb.st_size; > > /* Last access time */ > - sarray->base_addr[8 * stride] = sb.st_atime; > + if (sb.st_atime <= INT32_MAX) > + values->base_addr[8 * stride] = sb.st_atime; > > /* Last modification time */ > - sarray->base_addr[9 * stride] = sb.st_mtime; > + if (sb.st_mtime <= INT32_MAX) > + values->base_addr[9 * stride] = sb.st_mtime; > > /* Last file status change time */ > - sarray->base_addr[10 * stride] = sb.st_ctime; > + if (sb.st_ctime <= INT32_MAX) > + values->base_addr[10 * stride] = sb.st_ctime; > > /* Preferred I/O block size (-1 if not available) */ > #if HAVE_STRUCT_STAT_ST_BLKSIZE > - sarray->base_addr[11 * stride] = sb.st_blksize; > -#else > - sarray->base_addr[11 * stride] = -1; > + if (sb.st_blksize <= INT32_MAX) > + values->base_addr[11 * stride] = sb.st_blksize; > #endif > > /* Number of blocks allocated (-1 if not available) */ > #if HAVE_STRUCT_STAT_ST_BLOCKS > - sarray->base_addr[12 * stride] = sb.st_blocks; > -#else > - sarray->base_addr[12 * stride] = -1; > + if (sb.st_blocks <= INT32_MAX) > + values->base_addr[12 * stride] = sb.st_blocks; > #endif > } > > @@ -441,18 +467,18 @@ extern void fstat_i8_sub (GFC_INTEGER_8 *, gfc_array_i8 > *, GFC_INTEGER_8 *); > iexport_proto(fstat_i8_sub); > > void > -fstat_i8_sub (GFC_INTEGER_8 *unit, gfc_array_i8 *sarray, GFC_INTEGER_8 > *status) > +fstat_i8_sub (GFC_INTEGER_8 *unit, gfc_array_i8 *values, GFC_INTEGER_8 > *status) > { > int val; > struct stat sb; > > /* If the rank of the array is not 1, abort. */ > - if (GFC_DESCRIPTOR_RANK (sarray) != 1) > - runtime_error ("Array rank of SARRAY is not 1."); > + if (GFC_DESCRIPTOR_RANK (values) != 1) > + runtime_error ("Array rank of VALUES is not 1."); > > /* If the array is too small, abort. */ > - if (GFC_DESCRIPTOR_EXTENT(sarray,0) < 13) > - runtime_error ("Array size of SARRAY is too small."); > + if (GFC_DESCRIPTOR_EXTENT(values,0) < 13) > + runtime_error ("Array size of VALUES is too small."); > > /* Convert Fortran unit number to C file descriptor. */ > val = unit_to_fd ((int) *unit); > @@ -461,57 +487,57 @@ fstat_i8_sub (GFC_INTEGER_8 *unit, gfc_array_i8 > *sarray, GFC_INTEGER_8 *status) > > if (val == 0) > { > - index_type stride = GFC_DESCRIPTOR_STRIDE(sarray,0); > + index_type stride = GFC_DESCRIPTOR_STRIDE(values,0); > > /* Device ID */ > - sarray->base_addr[0] = sb.st_dev; > + values->base_addr[0] = sb.st_dev; > > /* Inode number */ > - sarray->base_addr[stride] = sb.st_ino; > + values->base_addr[stride] = sb.st_ino; > > /* File mode */ > - sarray->base_addr[2 * stride] = sb.st_mode; > + values->base_addr[2 * stride] = sb.st_mode; > > /* Number of (hard) links */ > - sarray->base_addr[3 * stride] = sb.st_nlink; > + values->base_addr[3 * stride] = sb.st_nlink; > > /* Owner's uid */ > - sarray->base_addr[4 * stride] = sb.st_uid; > + values->base_addr[4 * stride] = sb.st_uid; > > /* Owner's gid */ > - sarray->base_addr[5 * stride] = sb.st_gid; > + values->base_addr[5 * stride] = sb.st_gid; > > /* ID of device containing directory entry for file (0 if not > available) */ > #if HAVE_STRUCT_STAT_ST_RDEV > - sarray->base_addr[6 * stride] = sb.st_rdev; > + values->base_addr[6 * stride] = sb.st_rdev; > #else > - sarray->base_addr[6 * stride] = 0; > + values->base_addr[6 * stride] = 0; > #endif > > /* File size (bytes) */ > - sarray->base_addr[7 * stride] = sb.st_size; > + values->base_addr[7 * stride] = sb.st_size; > > /* Last access time */ > - sarray->base_addr[8 * stride] = sb.st_atime; > + values->base_addr[8 * stride] = sb.st_atime; > > /* Last modification time */ > - sarray->base_addr[9 * stride] = sb.st_mtime; > + values->base_addr[9 * stride] = sb.st_mtime; > > /* Last file status change time */ > - sarray->base_addr[10 * stride] = sb.st_ctime; > + values->base_addr[10 * stride] = sb.st_ctime; > > /* Preferred I/O block size (-1 if not available) */ > #if HAVE_STRUCT_STAT_ST_BLKSIZE > - sarray->base_addr[11 * stride] = sb.st_blksize; > + values->base_addr[11 * stride] = sb.st_blksize; > #else > - sarray->base_addr[11 * stride] = -1; > + values->base_addr[11 * stride] = -1; > #endif > > /* Number of blocks allocated (-1 if not available) */ > #if HAVE_STRUCT_STAT_ST_BLOCKS > - sarray->base_addr[12 * stride] = sb.st_blocks; > + values->base_addr[12 * stride] = sb.st_blocks; > #else > - sarray->base_addr[12 * stride] = -1; > + values->base_addr[12 * stride] = -1; > #endif > } > > @@ -524,10 +550,10 @@ extern GFC_INTEGER_4 fstat_i4 (GFC_INTEGER_4 *, > gfc_array_i4 *); > export_proto(fstat_i4); > > GFC_INTEGER_4 > -fstat_i4 (GFC_INTEGER_4 *unit, gfc_array_i4 *sarray) > +fstat_i4 (GFC_INTEGER_4 *unit, gfc_array_i4 *values) > { > GFC_INTEGER_4 val; > - fstat_i4_sub (unit, sarray, &val); > + fstat_i4_sub (unit, values, &val); > return val; > } > > @@ -535,10 +561,10 @@ extern GFC_INTEGER_8 fstat_i8 (GFC_INTEGER_8 *, > gfc_array_i8 *); > export_proto(fstat_i8); > > GFC_INTEGER_8 > -fstat_i8 (GFC_INTEGER_8 *unit, gfc_array_i8 *sarray) > +fstat_i8 (GFC_INTEGER_8 *unit, gfc_array_i8 *values) > { > GFC_INTEGER_8 val; > - fstat_i8_sub (unit, sarray, &val); > + fstat_i8_sub (unit, values, &val); > return val; > } > > -- > 2.43.0 > -- Steve