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 <[email protected]>
> 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