Dear all, the attached patch is a first attempt to fix some issues with the GNU intrinsics STAT/LSTAT/FSTAT which are g77 heritage. This patch is preparatory for dealing with the issue reported in PR82480 in that the default version of theses intrinsics use INTEGER(KIND=4) results that may overflow, unless -fdefault-integer-8 is used.
This patch consists of the following parts: - correct keyword names from g77 to gfortran implementation and manual - enhance checking of INTENT(OUT) arguments (VALUES, STATUS) - correct error messages in runtime library - for simplicity, variables have been consistently renamed in the present context ("array" -> "values"). - 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? Otherwise regtests here on x86_64-pc-linux-gnu without issues. OK for mainline? Thanks, Harald
From 0d283e310b8b4d5bac6a1354168fe3340e89d6d8 Mon Sep 17 00:00:00 2001 From: Harald Anlauf <anl...@gmx.de> Date: Wed, 11 Jun 2025 21:25:09 +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. Detect integer overflow assigning any of the stat components to VALUES, and return ERANGE in STATUS. (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 | 272 +++++++++++++++------------ 3 files changed, 226 insertions(+), 153 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..eb2779f887b 100644 --- a/libgfortran/intrinsics/stat.c +++ b/libgfortran/intrinsics/stat.c @@ -35,35 +35,36 @@ 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; char *str; struct stat sb; + bool ovf = false; /* 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,62 +81,75 @@ 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); /* Device ID */ - sarray->base_addr[0 * stride] = sb.st_dev; + ovf = INT32_MAX < sb.st_dev; + values->base_addr[0 * stride] = sb.st_dev; /* Inode number */ - sarray->base_addr[1 * stride] = sb.st_ino; + ovf |= INT32_MAX < sb.st_ino; + values->base_addr[1 * stride] = sb.st_ino; /* File mode */ - sarray->base_addr[2 * stride] = sb.st_mode; + ovf |= INT32_MAX < sb.st_mode; + values->base_addr[2 * stride] = sb.st_mode; /* Number of (hard) links */ - sarray->base_addr[3 * stride] = sb.st_nlink; + ovf |= INT32_MAX < sb.st_nlink; + values->base_addr[3 * stride] = sb.st_nlink; /* Owner's uid */ - sarray->base_addr[4 * stride] = sb.st_uid; + ovf |= INT32_MAX < sb.st_uid; + values->base_addr[4 * stride] = sb.st_uid; /* Owner's gid */ - sarray->base_addr[5 * stride] = sb.st_gid; + ovf |= INT32_MAX < 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; + ovf |= INT32_MAX < 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; + ovf |= INT32_MAX < sb.st_size; + values->base_addr[7 * stride] = sb.st_size; /* Last access time */ - sarray->base_addr[8 * stride] = sb.st_atime; + ovf |= INT32_MAX < sb.st_atime; + values->base_addr[8 * stride] = sb.st_atime; /* Last modification time */ - sarray->base_addr[9 * stride] = sb.st_mtime; + ovf |= INT32_MAX < sb.st_mtime; + values->base_addr[9 * stride] = sb.st_mtime; /* Last file status change time */ - sarray->base_addr[10 * stride] = sb.st_ctime; + ovf |= INT32_MAX < 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; + ovf |= INT32_MAX < 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; + ovf |= INT32_MAX < 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 } if (status != NULL) - *status = (val == 0) ? 0 : errno; + *status = (val == 0) ? (ovf ? ERANGE : 0) : errno; } @@ -144,10 +158,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 +171,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 +189,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 +211,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 +275,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 +289,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 +302,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 +313,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 +346,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 +358,33 @@ 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; + bool ovf = false; /* 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,62 +393,75 @@ 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); /* Device ID */ - sarray->base_addr[0 * stride] = sb.st_dev; + ovf = INT32_MAX < sb.st_dev; + values->base_addr[0 * stride] = sb.st_dev; /* Inode number */ - sarray->base_addr[1 * stride] = sb.st_ino; + ovf |= INT32_MAX < sb.st_ino; + values->base_addr[1 * stride] = sb.st_ino; /* File mode */ - sarray->base_addr[2 * stride] = sb.st_mode; + ovf |= INT32_MAX < sb.st_mode; + values->base_addr[2 * stride] = sb.st_mode; /* Number of (hard) links */ - sarray->base_addr[3 * stride] = sb.st_nlink; + ovf |= INT32_MAX < sb.st_nlink; + values->base_addr[3 * stride] = sb.st_nlink; /* Owner's uid */ - sarray->base_addr[4 * stride] = sb.st_uid; + ovf |= INT32_MAX < sb.st_uid; + values->base_addr[4 * stride] = sb.st_uid; /* Owner's gid */ - sarray->base_addr[5 * stride] = sb.st_gid; + ovf |= INT32_MAX < 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; + ovf |= INT32_MAX < 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; + ovf |= INT32_MAX < sb.st_size; + values->base_addr[7 * stride] = sb.st_size; /* Last access time */ - sarray->base_addr[8 * stride] = sb.st_atime; + ovf |= INT32_MAX < sb.st_atime; + values->base_addr[8 * stride] = sb.st_atime; /* Last modification time */ - sarray->base_addr[9 * stride] = sb.st_mtime; + ovf |= INT32_MAX < sb.st_mtime; + values->base_addr[9 * stride] = sb.st_mtime; /* Last file status change time */ - sarray->base_addr[10 * stride] = sb.st_ctime; + ovf |= INT32_MAX < 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; + ovf |= INT32_MAX < 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; + ovf |= INT32_MAX < 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 } if (status != NULL) - *status = (val == 0) ? 0 : errno; + *status = (val == 0) ? (ovf ? ERANGE : 0) : errno; } iexport(fstat_i4_sub); @@ -441,18 +469,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 +489,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 +552,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 +563,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