[Top][All Lists]
[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;
}
===============================================================================
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: perror bug,
Bruno Haible <=