aboutsummaryrefslogtreecommitdiff
path: root/libgfortran/io/read.c
diff options
context:
space:
mode:
authorJanne Blomqvist <jb@gcc.gnu.org>2014-11-13 14:05:01 +0200
committerJanne Blomqvist <jb@gcc.gnu.org>2014-11-13 14:05:01 +0200
commit581d232670be67eb51d3839c43f1113507a89185 (patch)
treec1593d21b75ed82f1d44f238217eb2c1724e03ac /libgfortran/io/read.c
parent95cc11e1634c8faa09ab161564a13c1ae9ec1794 (diff)
downloadgcc-581d232670be67eb51d3839c43f1113507a89185.zip
gcc-581d232670be67eb51d3839c43f1113507a89185.tar.gz
gcc-581d232670be67eb51d3839c43f1113507a89185.tar.bz2
PR 60324 Unbounded stack allocations in libgfortran.
2014-11-13 Janne Blomqvist <jb@gcc.gnu.org> PR libfortran/60324 * configure: Regenerated. * configure.ac (AM_CFLAGS): Add Werror=vla. * libgfortran.h (gfc_alloca): Remove macro. (fc_strdup_notrim): New prototype. * intrinsics/access.c (access_func): Use fc_strdup rather than stack allocation. * intrinsics/chdir.c (chdir_i4_sub): Likewise. (chdir_i8_sub): Likewise. * intrinsics/chmod.c (chmod_internal): New function, move logic here. (chmod_func): Call chmod_internal. * intrinsics/env.c (getenv): Use fc_strdup rather than stack allocation. (get_environment_variable_i4): Likewise. * intrinsics/execute_command_line.c (execute_command_line): Likewise. * intrinsics/hostnm.c (hostnm_0): New function, use static buffer rather than VLA. (hostnm_i4_sub): Call hostnm_0. (hostnm_i8_sub): Likewise. (hostnm): Likewise. * intrinsics/link.c (link_internal): New function, use fc_strdup rather than stack allocation. (link_i4_sub): Call link_internal. (link_i8_sub): Likewise. (link_i4): Likewise. (link_i8): Likewise. * intrinsics/perror.c (perror_sub): Use fc_strdup rather than stack allocation. * intrinsics/random.c (random_seed_i4): Use static buffer rather than VLA, use _Static_assert to make sure it's big enough. * intrinsics/rename.c (rename_internal): New function, use fc_strdup rather than stack allocation. (rename_i4_sub): Call rename_internal. (rename_i8_sub): Likewise. (rename_i4): Likewise. (rename_i8): Likewise. * intrinsics/stat.c (stat_i4_sub_0): Use fc_strdup rather than stack allocation. (stat_i8_sub_0): Likewise. * intrinsics/symlink.c (symlnk_internal): New function, use fc_strdup rather than stack allocation. (symlnk_i4_sub): Call symlnk_internal. (symlnk_i8_sub): Likewise. (symlnk_i4): Likewise. (symlnk_i8): Likewise. * intrinsics/system.c (system_sub): Use fc_strdup rather than stack allocation. * intrinsics/unlink.c (unlink_i4_sub): Likewise. * io/file_pos.c (READ_CHUNK): Make it a macro rather than variable. * io/list_read.c (nml_get_obj_data): Use fixed stack buffer, fall back to xmalloc/free for large sizes. * io/read.c (read_f): Likewise. * io/transfer.c (MAX_READ): Make it a macro rather than variable. (WRITE_CHUNK): Likewise. * io/write_float.def (write_float): Use fixed stack buffer, fall back to xmalloc/free for large sizes. * runtime/string.c (fc_strdup_notrim): New function. From-SVN: r217480
Diffstat (limited to 'libgfortran/io/read.c')
-rw-r--r--libgfortran/io/read.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c
index 64f2ddf..5c56dc2 100644
--- a/libgfortran/io/read.c
+++ b/libgfortran/io/read.c
@@ -881,6 +881,9 @@ read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
void
read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
{
+#define READF_TMP 50
+ char tmp[READF_TMP];
+ size_t buf_size = 0;
int w, seen_dp, exponent;
int exponent_sign;
const char *p;
@@ -895,6 +898,7 @@ read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
exponent_sign = 1;
exponent = 0;
w = f->u.w;
+ buffer = tmp;
/* Read in the next block. */
p = read_block_form (dtp, &w);
@@ -911,7 +915,10 @@ read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
exponent because of an implicit decimal point or the like. Thus allocating
strlen ("+0.0e-1000") == 10 characters plus one for NUL more than the
original buffer had should be enough. */
- buffer = gfc_alloca (w + 11);
+ buf_size = w + 11;
+ if (buf_size > READF_TMP)
+ buffer = xmalloc (buf_size);
+
out = buffer;
/* Optional sign */
@@ -984,6 +991,8 @@ read_f (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
goto bad_float;
convert_infnan (dtp, dest, buffer, length);
+ if (buf_size > READF_TMP)
+ free (buffer);
return;
}
@@ -1170,7 +1179,8 @@ done:
/* Do the actual conversion. */
convert_real (dtp, dest, buffer, length);
-
+ if (buf_size > READF_TMP)
+ free (buffer);
return;
/* The value read is zero. */
@@ -1203,6 +1213,8 @@ zero:
return;
bad_float:
+ if (buf_size > READF_TMP)
+ free (buffer);
generate_error (&dtp->common, LIBERROR_READ_VALUE,
"Bad value during floating point read");
next_record (dtp, 1);