Fix stack overflow crash in getcwd intrinsic.

2014-05-12  Janne Blomqvist  <jb@gcc.gnu.org>

	PR libfortran/61035
	* intrinsics/getcwd.c (getcwd_i4_sub): Avoid potentially large
	stack allocation, avoid extra copying in the common case.

From-SVN: r210335
This commit is contained in:
Janne Blomqvist 2014-05-12 22:23:11 +03:00
parent f7b6856fa4
commit 16e60fff0b
2 changed files with 32 additions and 11 deletions

View File

@ -1,3 +1,9 @@
2014-05-12 Janne Blomqvist <jb@gcc.gnu.org>
PR libfortran/61035
* intrinsics/getcwd.c (getcwd_i4_sub): Avoid potentially large
stack allocation, avoid extra copying in the common case.
2014-05-12 Janne Blomqvist <jb@gcc.gnu.org>
* configure.ac (AM_CFLAGS): Use -std=gnu11.

View File

@ -2,7 +2,7 @@
Copyright (C) 2004-2014 Free Software Foundation, Inc.
Contributed by Steven G. Kargl <kargls@comcast.net>.
This file is part of the GNU Fortran 95 runtime library (libgfortran).
This file is part of the GNU Fortran runtime library (libgfortran).
Libgfortran is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
@ -40,20 +40,35 @@ iexport_proto(getcwd_i4_sub);
void
getcwd_i4_sub (char *cwd, GFC_INTEGER_4 *status, gfc_charlen_type cwd_len)
{
char str[cwd_len + 1];
GFC_INTEGER_4 stat;
int err;
memset(cwd, ' ', (size_t) cwd_len);
if (!getcwd (str, (size_t) cwd_len + 1))
stat = errno;
else
if (getcwd (cwd, cwd_len))
{
stat = 0;
memcpy (cwd, str, strlen (str));
size_t len = strlen (cwd);
memset (cwd + len, ' ', cwd_len - len);
err = 0;
}
else if (errno == ERANGE)
{
/* There is a possibility that the previous attempt failed due
to not enough space for the terminating null byte. Try again
with a buffer one char longer. */
char *buf = xmalloc (cwd_len + 1);
if (getcwd (buf, cwd_len + 1))
{
memcpy (cwd, buf, cwd_len);
err = 0;
}
else
err = errno;
free (buf);
}
else
err = errno;
if (err)
memset (cwd, ' ', cwd_len);
if (status != NULL)
*status = stat;
*status = err;
}
iexport(getcwd_i4_sub);