bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: perror bug


From: Bruno Haible
Subject: Re: perror bug
Date: Mon, 14 Mar 2011 09:53:23 +0100
User-agent: KMail/1.9.9

Eric Blake wrote on 2011-02-10:
> POSIX requires that this program have an identical first and last line:
> 
> #include <stdio.h>
> #include <string.h>
> #include <errno.h>
> int main (void) {
>   char *err = strerror(1000);
>   printf ("%s\n", err);
>   errno = 2000;
>   perror ("hi");
>   printf ("%s\n", err);
>   return 0;
> }
> 
> but on cygwin 1.7.7, the perror() corrupts the buffer returned by
> strerror().  We should probably fix that in gnulib as part of our perror
> module.

Yes, but first let's see which other problems there are.

The program below tests whether strerror's buffer is read-write (i.e.
whether it is overwritten by subsequent strerror calls) and, when compiled
with -DPERROR, whether perror calls clobber the strerror buffer.

The result is:

           read-write buffer?    perror reuses strerror buffer?
glibc           yes                   no
OpenBSD         yes                   no
OSF/1           yes                   no
Cygwin 1.5      yes                   yes
Cygwin 1.7      yes                   yes
mingw           yes                   no

That's the situation without gnulib. With gnulib, there are three problems
in toto:
  1) The strerror_r replacement, when EXTEND_STRERROR_R is defined,
     clobbers the strerror function's buffer, which it shouldn't.
  2) The perror replacement uses strerror, thus clobbering the strerror
     buffer.
  3) On Cygwin, perror clobbers the strerror buffer.

The fix for 1) should be to move most of lib/strerror.c to lib/strerror_r.c.
The fix for 2) should be to change lib/perror.c to call strerror_r.
The fix for 3) should be to change m4/perror.m4 to enable the replacement
on Cygwin.

I think the three fixes should be applied in this order, bottom-up.

Bruno


==================================== foo.c ====================================
#include <errno.h>
#include <stdio.h>
#include <string.h>

int main ()
{
  const char *msg1;
  const char *msg2;
  const char *msg3;

  msg1 = strerror (ENOENT);
  printf ("msg1 before: %s\n", msg1);
  msg2 = strerror (-4);
  printf ("msg2 before: %s\n", msg2);
  msg3 = strerror (1729576);
  printf ("msg3 before: %s\n", msg3);

  freopen ("/dev/null", "w", stderr);

#ifdef PERROR
  errno = EACCES; perror ("");
  errno = -5; perror ("");
  errno = 153272; perror ("");
#else
  strerror (EACCES);
  strerror (-5);
  strerror (153272);
#endif

  printf ("msg1 after:  %s\n", msg1);
  printf ("msg2 after:  %s\n", msg2);
  printf ("msg3 after:  %s\n", msg3);

  return 0;
}
===============================================================================



reply via email to

[Prev in Thread] Current Thread [Next in Thread]