Re: [PATCH, libgfortran] PR 60324 Unbounded stack allocations in libgfortran

2014-11-15 Thread Janne Blomqvist
On Sat, Nov 15, 2014 at 8:01 AM, Janne Blomqvist
blomqvist.ja...@gmail.com wrote:
 On Fri, Nov 14, 2014 at 11:02 PM, Tobias Burnus bur...@net-b.de wrote:
 I think instead of doing a run-time check I'd prefer something like the
 following, keeping the compile-time assert.

 --- a/libgfortran/intrinsics/random.c
 +++ b/libgfortran/intrinsics/random.c
 @@ -253 +253 @@ static GFC_UINTEGER_4 kiss_default_seed[] = {
 -static const GFC_INTEGER_4 kiss_size =
 sizeof(kiss_seed)/sizeof(kiss_seed[0]);
 +#define KISS_SIZE ((GFC_INTEGER_4) (sizeof(kiss_seed)/sizeof(kiss_seed[0]))

 (plus s/kiss_size/KISS_SIZE/ changes in the code.)

 Janne, what do you think?

 I like it. With this, you can also get rid of the assert and the newly
 introduced KISS_MAX_SIZE macro, and just make the seed array the
 correct size, as was originally done (with a VLA). Consider such a
 patch pre-approved.

I went ahead and did it myself, committed the attached patch as
r217623 after regtesting.

2014-11-16  Janne Blomqvist  j...@gcc.gnu.org

PR libfortran/60324
* intrinsics/random.c (kiss_size): Rename to KISS_SIZE, make it a
macro instead of a variable.
(random_seed_i4): Make seed correct size, remove assert, KISS_SIZE
related changes.
(random_seed_i8): KISS_SIZE related changes.


-- 
Janne Blomqvist
diff --git a/libgfortran/intrinsics/random.c b/libgfortran/intrinsics/random.c
index 5e91929..d2510b2 100644
--- a/libgfortran/intrinsics/random.c
+++ b/libgfortran/intrinsics/random.c
@@ -224,7 +224,7 @@ KISS algorithm.  */
z=0,c=0 and z=2^32-1,c=698769068
should be avoided.  */
 
-/* Any modifications to the seeds that change kiss_size below need to be
+/* Any modifications to the seeds that change KISS_SIZE below need to be
reflected in check.c (gfc_check_random_seed) to enable correct
compile-time checking of PUT size for the RANDOM_SEED intrinsic.  */
 
@@ -250,7 +250,7 @@ static GFC_UINTEGER_4 kiss_default_seed[] = {
 #endif
 };
 
-static const GFC_INTEGER_4 kiss_size = sizeof(kiss_seed)/sizeof(kiss_seed[0]);
+#define KISS_SIZE (sizeof(kiss_seed)/sizeof(kiss_seed[0]))
 
 static GFC_UINTEGER_4 * const kiss_seed_1 = kiss_seed;
 static GFC_UINTEGER_4 * const kiss_seed_2 = kiss_seed + 4;
@@ -665,12 +665,7 @@ unscramble_seed (unsigned char *dest, unsigned char *src, 
int size)
 void
 random_seed_i4 (GFC_INTEGER_4 *size, gfc_array_i4 *put, gfc_array_i4 *get)
 {
-  int i;
-
-#define KISS_MAX_SIZE 12
-  unsigned char seed[4 * KISS_MAX_SIZE];
-  _Static_assert (kiss_size = KISS_MAX_SIZE,
- kiss_size must = KISS_MAX_SIZE);
+  unsigned char seed[4 * KISS_SIZE];
 
   __gthread_mutex_lock (random_lock);
 
@@ -681,11 +676,11 @@ random_seed_i4 (GFC_INTEGER_4 *size, gfc_array_i4 *put, 
gfc_array_i4 *get)
   /* From the standard: If no argument is present, the processor assigns
  a processor-dependent value to the seed.  */
   if (size == NULL  put == NULL  get == NULL)
-  for (i = 0; i  kiss_size; i++)
+  for (size_t i = 0; i  KISS_SIZE; i++)
kiss_seed[i] = kiss_default_seed[i];
 
   if (size != NULL)
-*size = kiss_size;
+*size = KISS_SIZE;
 
   if (put != NULL)
 {
@@ -694,18 +689,18 @@ random_seed_i4 (GFC_INTEGER_4 *size, gfc_array_i4 *put, 
gfc_array_i4 *get)
 runtime_error (Array rank of PUT is not 1.);
 
   /* If the array is too small, abort.  */
-  if (GFC_DESCRIPTOR_EXTENT(put,0)  kiss_size)
+  if (GFC_DESCRIPTOR_EXTENT(put,0)  (index_type) KISS_SIZE)
 runtime_error (Array size of PUT is too small.);
 
   /*  We copy the seed given by the user.  */
-  for (i = 0; i  kiss_size; i++)
+  for (size_t i = 0; i  KISS_SIZE; i++)
memcpy (seed + i * sizeof(GFC_UINTEGER_4),
-   (put-base_addr[(kiss_size - 1 - i) * 
GFC_DESCRIPTOR_STRIDE(put,0)]),
+   (put-base_addr[(KISS_SIZE - 1 - i) * 
GFC_DESCRIPTOR_STRIDE(put,0)]),
sizeof(GFC_UINTEGER_4));
 
   /* We put it after scrambling the bytes, to paper around users who
 provide seeds with quality only in the lower or upper part.  */
-  scramble_seed ((unsigned char *) kiss_seed, seed, 4*kiss_size);
+  scramble_seed ((unsigned char *) kiss_seed, seed, 4 * KISS_SIZE);
 }
 
   /* Return the seed to GET data.  */
@@ -716,15 +711,15 @@ random_seed_i4 (GFC_INTEGER_4 *size, gfc_array_i4 *put, 
gfc_array_i4 *get)
runtime_error (Array rank of GET is not 1.);
 
   /* If the array is too small, abort.  */
-  if (GFC_DESCRIPTOR_EXTENT(get,0)  kiss_size)
+  if (GFC_DESCRIPTOR_EXTENT(get,0)  (index_type) KISS_SIZE)
runtime_error (Array size of GET is too small.);
 
   /* Unscramble the seed.  */
-  unscramble_seed (seed, (unsigned char *) kiss_seed, 4*kiss_size);
+  unscramble_seed (seed, (unsigned char *) kiss_seed, 4 * KISS_SIZE);
 
   /*  Then copy it back to the user variable.  */
-  for (i = 0; i  kiss_size; i++)
-   memcpy ((get-base_addr[(kiss_size - 1 - i) * 

Re: [PATCH, libgfortran] PR 60324 Unbounded stack allocations in libgfortran

2014-11-14 Thread Cesar Philippidis
On 11/13/2014 02:32 AM, Janne Blomqvist wrote:

 in the spirit of PR 60324 and 61035, here's a patch that gets rid of
 the remaining potentially unbounded stack allocations in libgfortran.
 All uses of __builtin_alloca() and VLA's are replaced either straight
 with heap allocated memory, or with a fixed size stack buffer,
 potentially switching to heap storage for large sizes in places where
 performance might matter. In order to avoid reintroducing these kinds
 of issues, I also added -Werror=vla to AM_CFLAGS.
 
 This might also help limited targets like nvptx that lack VLA's.
 
 Regtested on x86_64-unknown-linux-gnu, Ok for trunk?

I hit an error when building intrinsics/random.c:

  error: expression in static assertion is not constant

Joseph told me that static const variables cannot be used in constant
expressions in C, so I've replaced the _Static_assert with a regular
assert. Are you using g++ to build libgfortran?

I don't have a good baseline test this patch thoroughly, but at least I
can bootstrap gcc without it failing in libgfortran. Is this OK for
mainline and/or could someone see if it causes any regressions?

Thanks,
Cesar
2014-11-14  Cesar Philippidis  ce...@codesourcery.com

	libgfortran/
	* intrinsics/random.c (random_seed_i4): Replace _Static_assert
	with assert.


diff --git a/libgfortran/intrinsics/random.c b/libgfortran/intrinsics/random.c
index 5e91929..6b07a66d 100644
--- a/libgfortran/intrinsics/random.c
+++ b/libgfortran/intrinsics/random.c
@@ -25,6 +25,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 http://www.gnu.org/licenses/.  */
 
 #include libgfortran.h
+#include assert.h
 #include gthr.h
 #include string.h
 
@@ -669,8 +670,8 @@ random_seed_i4 (GFC_INTEGER_4 *size, gfc_array_i4 *put, gfc_array_i4 *get)
 
 #define KISS_MAX_SIZE 12
   unsigned char seed[4 * KISS_MAX_SIZE];
-  _Static_assert (kiss_size = KISS_MAX_SIZE,
-		  kiss_size must = KISS_MAX_SIZE);
+  assert (kiss_size = KISS_MAX_SIZE
+	   kiss_size must = KISS_MAX_SIZE);
 
   __gthread_mutex_lock (random_lock);
 


Re: [PATCH, libgfortran] PR 60324 Unbounded stack allocations in libgfortran

2014-11-14 Thread Tobias Burnus

Cesar Philippidis wrote:

On 11/13/2014 02:32 AM, Janne Blomqvist wrote:
I hit an error when building intrinsics/random.c:
   error: expression in static assertion is not constant
Joseph told me that static const variables cannot be used in constant
expressions in C, so I've replaced the _Static_assert with a regular
assert. Are you using g++ to build libgfortran?


I wonder why you are seeing this while others aren't. It seemed to work 
for me, gcc-testresults looks fine and there weren't complaints 
yesterday or today. (The patch was committed 34 h ago.)


The default build should use gcc and not g++.


I don't have a good baseline test this patch thoroughly, but at least I
can bootstrap gcc without it failing in libgfortran. Is this OK for
mainline and/or could someone see if it causes any regressions?


I think instead of doing a run-time check I'd prefer something like the 
following, keeping the compile-time assert.


--- a/libgfortran/intrinsics/random.c
+++ b/libgfortran/intrinsics/random.c
@@ -253 +253 @@ static GFC_UINTEGER_4 kiss_default_seed[] = {
-static const GFC_INTEGER_4 kiss_size = 
sizeof(kiss_seed)/sizeof(kiss_seed[0]);

+#define KISS_SIZE ((GFC_INTEGER_4) (sizeof(kiss_seed)/sizeof(kiss_seed[0]))

(plus s/kiss_size/KISS_SIZE/ changes in the code.)

Janne, what do you think?

Tobias


Re: [PATCH, libgfortran] PR 60324 Unbounded stack allocations in libgfortran

2014-11-14 Thread Janne Blomqvist
On Fri, Nov 14, 2014 at 11:02 PM, Tobias Burnus bur...@net-b.de wrote:
 Cesar Philippidis wrote:

 On 11/13/2014 02:32 AM, Janne Blomqvist wrote:
 I hit an error when building intrinsics/random.c:
error: expression in static assertion is not constant
 Joseph told me that static const variables cannot be used in constant
 expressions in C, so I've replaced the _Static_assert with a regular
 assert. Are you using g++ to build libgfortran?


 I wonder why you are seeing this while others aren't.

Yeah, I wonder the same?

 I don't have a good baseline test this patch thoroughly, but at least I
 can bootstrap gcc without it failing in libgfortran. Is this OK for
 mainline and/or could someone see if it causes any regressions?


 I think instead of doing a run-time check I'd prefer something like the
 following, keeping the compile-time assert.

 --- a/libgfortran/intrinsics/random.c
 +++ b/libgfortran/intrinsics/random.c
 @@ -253 +253 @@ static GFC_UINTEGER_4 kiss_default_seed[] = {
 -static const GFC_INTEGER_4 kiss_size =
 sizeof(kiss_seed)/sizeof(kiss_seed[0]);
 +#define KISS_SIZE ((GFC_INTEGER_4) (sizeof(kiss_seed)/sizeof(kiss_seed[0]))

 (plus s/kiss_size/KISS_SIZE/ changes in the code.)

 Janne, what do you think?

I like it. With this, you can also get rid of the assert and the newly
introduced KISS_MAX_SIZE macro, and just make the seed array the
correct size, as was originally done (with a VLA). Consider such a
patch pre-approved.


-- 
Janne Blomqvist


Re: [PATCH, libgfortran] PR 60324 Unbounded stack allocations in libgfortran

2014-11-14 Thread Cesar Philippidis
On 11/14/2014 10:01 PM, Janne Blomqvist wrote:
 On Fri, Nov 14, 2014 at 11:02 PM, Tobias Burnus bur...@net-b.de wrote:
 Cesar Philippidis wrote:

 On 11/13/2014 02:32 AM, Janne Blomqvist wrote:
 I hit an error when building intrinsics/random.c:
error: expression in static assertion is not constant
 Joseph told me that static const variables cannot be used in constant
 expressions in C, so I've replaced the _Static_assert with a regular
 assert. Are you using g++ to build libgfortran?


 I wonder why you are seeing this while others aren't.
 
 Yeah, I wonder the same?

It does seem strange. Maybe that function isn't necessary for all
targets? I've attached a reduced test case if anyone is interested in
it. That error should show up with gcc random.c.

 I don't have a good baseline test this patch thoroughly, but at least I
 can bootstrap gcc without it failing in libgfortran. Is this OK for
 mainline and/or could someone see if it causes any regressions?


 I think instead of doing a run-time check I'd prefer something like the
 following, keeping the compile-time assert.

 --- a/libgfortran/intrinsics/random.c
 +++ b/libgfortran/intrinsics/random.c
 @@ -253 +253 @@ static GFC_UINTEGER_4 kiss_default_seed[] = {
 -static const GFC_INTEGER_4 kiss_size =
 sizeof(kiss_seed)/sizeof(kiss_seed[0]);
 +#define KISS_SIZE ((GFC_INTEGER_4) (sizeof(kiss_seed)/sizeof(kiss_seed[0]))

 (plus s/kiss_size/KISS_SIZE/ changes in the code.)

 Janne, what do you think?
 
 I like it. With this, you can also get rid of the assert and the newly
 introduced KISS_MAX_SIZE macro, and just make the seed array the
 correct size, as was originally done (with a VLA). Consider such a
 patch pre-approved.

Thanks for fixing this!

Cesar

#include stdint.h

typedef int32_t GFC_INTEGER_4;
typedef uint32_t GFC_UINTEGER_4;

static const GFC_UINTEGER_4 kiss_seed[] = {
  123456789, 362436069, 521288629, 316191069,
  987654321, 458629013, 582859209, 438195021,

  573658661, 185639104, 582619469, 296736107

};

static const GFC_INTEGER_4 kiss_size = sizeof(kiss_seed)/sizeof(kiss_seed[0]);

int
main ()
{
#define KISS_MAX_SIZE 12
  unsigned char seed[4 * 12];

  _Static_assert (kiss_size = 12, kiss_size must = KISS_MAX_SIZE);
  //static_assert (kiss_size = 12, kiss_size must = KISS_MAX_SIZE);

  return 0;
}


Re: [PATCH, libgfortran] PR 60324 Unbounded stack allocations in libgfortran

2014-11-13 Thread FX
 Regtested on x86_64-unknown-linux-gnu, Ok for trunk?

OK two me, with three comments:

* intrinsics/chmod.c (chmod_internal): New function, move logic
here.
(chmod_func): Call chmod_internal.

Not sure what’s the need / benefit from this, given the function is only called 
once.

* intrinsics/random.c (random_seed_i4): Use static buffer rather
than VLA, use _Static_assert to make sure it's big enough.

This array has constant size, known at compilation time. Isn’t it allowed to 
have an array with “const int” as size? I though it was.

* io/read.c (read_f): Likewise.

Is the known upper bound you have chosen (#define READF_TMP 50) compatible with 
the largest float we support, i.e. real(16)?
So that we avoid using allocation for reading data we have written ourselves in 
default format :)


FX

Re: [PATCH, libgfortran] PR 60324 Unbounded stack allocations in libgfortran

2014-11-13 Thread Janne Blomqvist
On Thu, Nov 13, 2014 at 1:31 PM, FX fxcoud...@gmail.com wrote:
 Regtested on x86_64-unknown-linux-gnu, Ok for trunk?

 OK two me, with three comments:

* intrinsics/chmod.c (chmod_internal): New function, move logic
here.
(chmod_func): Call chmod_internal.

 Not sure what’s the need / benefit from this, given the function is only 
 called once.

Just a convenience; chmod_internal returns from quite a few places.
Rather than sprinkling free() calls before all those, I used a wrapper
function. As it's called only once, and it's a static function, it
should be inlined anyway.

* intrinsics/random.c (random_seed_i4): Use static buffer rather
than VLA, use _Static_assert to make sure it's big enough.

 This array has constant size, known at compilation time. Isn’t it allowed to 
 have an array with “const int” as size? I though it was.

I originally thought so, but apparently not, as it fails to compile
with -Werror=vla. Same for the other couple places where I replaced a
static const variable with a macro. The reason might be that the
const-ness can be casted away, and then one can write to the variable?

* io/read.c (read_f): Likewise.

 Is the known upper bound you have chosen (#define READF_TMP 50) compatible 
 with the largest float we support, i.e. real(16)?
 So that we avoid using allocation for reading data we have written ourselves 
 in default format :)

Yeah, I used the test program below:

program maxgf
  implicit none
  print *, huge(0._10)
  print *, -huge(0._16)
  print *, '123456789012345678901234567890123456789012345678901234567890'
end program maxgf

= something like 45 characters should be enough. Then I added a few
extra just to be sure to cover all the common cases.


Thanks for the quick review, committed as r217480.

-- 
Janne Blomqvist


Re: [PATCH, libgfortran] PR 60324 Unbounded stack allocations in libgfortran

2014-11-13 Thread Marek Polacek
On Thu, Nov 13, 2014 at 02:05:52PM +0200, Janne Blomqvist wrote:
 Thanks for the quick review, committed as r217480.

This broke bootstrap because of implicit declaration of free.

The following (untested) should fix it, ok for trunk?

2014-11-13  Marek Polacek  pola...@redhat.com

* intrinsics/access.c: Include stdlib.h.
* intrinsics/chdir.c: Likewise.
* intrinsics/chmod.c: Likewise.

diff --git gcc/intrinsics/access.c gcc/intrinsics/access.c
index 65a0a10..0c18da0 100644
--- gcc/intrinsics/access.c
+++ gcc/intrinsics/access.c
@@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #include libgfortran.h
 
 #include errno.h
+#include stdlib.h
 #include string.h
 
 #ifdef HAVE_UNISTD_H
diff --git gcc/intrinsics/chdir.c gcc/intrinsics/chdir.c
index 87419a8..193e482 100644
--- gcc/intrinsics/chdir.c
+++ gcc/intrinsics/chdir.c
@@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #include libgfortran.h
 
 #include errno.h
+#include stdlib.h
 #include string.h
 
 #ifdef HAVE_UNISTD_H
diff --git gcc/intrinsics/chmod.c gcc/intrinsics/chmod.c
index c42fa8c..bdcb676 100644
--- gcc/intrinsics/chmod.c
+++ gcc/intrinsics/chmod.c
@@ -28,6 +28,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #if defined(HAVE_SYS_STAT_H)
 
 #include string.h/* For memcpy. */
+#include stdlib.h/* For free.  */
 #include sys/stat.h  /* For stat, chmod and umask.  */
 
 
Marek


Re: [PATCH, libgfortran] PR 60324 Unbounded stack allocations in libgfortran

2014-11-13 Thread Jakub Jelinek
On Thu, Nov 13, 2014 at 04:57:08PM +0100, Marek Polacek wrote:
 On Thu, Nov 13, 2014 at 02:05:52PM +0200, Janne Blomqvist wrote:
  Thanks for the quick review, committed as r217480.
 
 This broke bootstrap because of implicit declaration of free.
 
 The following (untested) should fix it, ok for trunk?
 
 2014-11-13  Marek Polacek  pola...@redhat.com
 
   * intrinsics/access.c: Include stdlib.h.
   * intrinsics/chdir.c: Likewise.
   * intrinsics/chmod.c: Likewise.

Ok, thanks.

Jakub


Re: [PATCH, libgfortran] PR 60324 Unbounded stack allocations in libgfortran

2014-11-13 Thread Marek Polacek
On Thu, Nov 13, 2014 at 04:59:09PM +0100, Jakub Jelinek wrote:
 On Thu, Nov 13, 2014 at 04:57:08PM +0100, Marek Polacek wrote:
  On Thu, Nov 13, 2014 at 02:05:52PM +0200, Janne Blomqvist wrote:
   Thanks for the quick review, committed as r217480.
  
  This broke bootstrap because of implicit declaration of free.
  
  The following (untested) should fix it, ok for trunk?
  
  2014-11-13  Marek Polacek  pola...@redhat.com
  
  * intrinsics/access.c: Include stdlib.h.
  * intrinsics/chdir.c: Likewise.
  * intrinsics/chmod.c: Likewise.
 
 Ok, thanks.

The previous version was incomplete.  The following should be.

Applying to trunk.

2014-11-13  Marek Polacek  pola...@redhat.com

* intrinsics/access.c: Include stdlib.h.
* intrinsics/chdir.c: Likewise.
* intrinsics/chmod.c: Likewise.
* intrinsics/link.c: Likewise.
* intrinsics/perror.c: Likewise.
* intrinsics/rename.c: Likewise.
* intrinsics/symlnk.c: Likewise.
* intrinsics/unlink.c: Likewise.

diff --git gcc/intrinsics/access.c gcc/intrinsics/access.c
index 65a0a10..0c18da0 100644
--- gcc/intrinsics/access.c
+++ gcc/intrinsics/access.c
@@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #include libgfortran.h
 
 #include errno.h
+#include stdlib.h
 #include string.h
 
 #ifdef HAVE_UNISTD_H
diff --git gcc/intrinsics/chdir.c gcc/intrinsics/chdir.c
index 87419a8..193e482 100644
--- gcc/intrinsics/chdir.c
+++ gcc/intrinsics/chdir.c
@@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #include libgfortran.h
 
 #include errno.h
+#include stdlib.h
 #include string.h
 
 #ifdef HAVE_UNISTD_H
diff --git gcc/intrinsics/chmod.c gcc/intrinsics/chmod.c
index c42fa8c..bdcb676 100644
--- gcc/intrinsics/chmod.c
+++ gcc/intrinsics/chmod.c
@@ -28,6 +28,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #if defined(HAVE_SYS_STAT_H)
 
 #include string.h/* For memcpy. */
+#include stdlib.h/* For free.  */
 #include sys/stat.h  /* For stat, chmod and umask.  */
 
 
diff --git gcc/intrinsics/link.c gcc/intrinsics/link.c
index c6084a1..dd9c470 100644
--- gcc/intrinsics/link.c
+++ gcc/intrinsics/link.c
@@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #include libgfortran.h
 
 #include errno.h
+#include stdlib.h
 #include string.h
 
 #ifdef HAVE_UNISTD_H
diff --git gcc/intrinsics/perror.c gcc/intrinsics/perror.c
index a8f0972..2bb1305 100644
--- gcc/intrinsics/perror.c
+++ gcc/intrinsics/perror.c
@@ -27,6 +27,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 
 #include errno.h
 #include string.h
+#include stdlib.h
 
 /* SUBROUTINE PERROR(STRING)
CHARACTER(len=*), INTENT(IN) :: STRING   */
diff --git gcc/intrinsics/rename.c gcc/intrinsics/rename.c
index aabf821..78c3d81 100644
--- gcc/intrinsics/rename.c
+++ gcc/intrinsics/rename.c
@@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #include libgfortran.h
 
 #include errno.h
+#include stdlib.h
 #include string.h
 
 
diff --git gcc/intrinsics/symlnk.c gcc/intrinsics/symlnk.c
index 5c53cb7..52a3c4b 100644
--- gcc/intrinsics/symlnk.c
+++ gcc/intrinsics/symlnk.c
@@ -26,6 +26,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 #include libgfortran.h
 
 #include errno.h
+#include stdlib.h
 #include string.h
 
 #ifdef HAVE_UNISTD_H
diff --git gcc/intrinsics/unlink.c gcc/intrinsics/unlink.c
index 2971a62..4752988 100644
--- gcc/intrinsics/unlink.c
+++ gcc/intrinsics/unlink.c
@@ -25,6 +25,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If 
not, see
 
 #include libgfortran.h
 
+#include stdlib.h
 #include string.h
 #include errno.h
 

Marek