+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.
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
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);