On 2011-14-03 I wrote in
<http://lists.gnu.org/archive/html/bug-gnulib/2011-03/msg00117.html>:
>   2) The perror replacement uses strerror, thus clobbering the strerror
>      buffer.
>   3) On Cygwin, perror clobbers the strerror buffer.
> 
> 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.

Here comes part 2. Eric, I leave part 3 to you.


2011-05-19  Bruno Haible  <br...@clisp.org>

        perror: Avoid clobbering the strerror buffer when possible.
        * lib/strerror-impl.h: New file, extracted from lib/strerror.c.
        * lib/strerror.c: Include it.
        * modules/strerror (Files): Add lib/strerror-impl.h.
        * lib/perror.c: Include <stdlib.h>, intprops.h, verify.h.
        (my_strerror): New function, defined through lib/strerror-impl.h.
        (perror): Use it instead of strerror.
        * modules/perror (Files): Add lib/strerror-impl.h.
        (Depends-on): Remove strerror. Add intprops, verify, strerror_r-posix.

============================= lib/strerror-impl.h =============================
/* strerror-impl.h --- Implementation of POSIX compatible strerror() function.

   Copyright (C) 2007-2011 Free Software Foundation, Inc.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

#ifdef STATIC
STATIC
#endif
char *
strerror (int n)
{
  static char buf[256];

  int ret = strerror_r (n, buf, sizeof (buf));

  if (ret == 0)
    return buf;

  if (ret == ERANGE)
    /* If this happens, increase the size of buf.  */
    abort ();

  {
    static char const fmt[] = "Unknown error (%d)";
    verify (sizeof (buf) >= sizeof (fmt) + INT_STRLEN_BOUND (n));
    sprintf (buf, fmt, n);
    return buf;
  }
}
===============================================================================
--- lib/perror.c.orig   Thu May 19 21:44:53 2011
+++ lib/perror.c        Thu May 19 21:40:43 2011
@@ -21,12 +21,26 @@
 #include <stdio.h>
 
 #include <errno.h>
+#include <stdlib.h>
 #include <string.h>
 
+#include "intprops.h"
+#include "verify.h"
+
+/* Use the system functions, not the gnulib overrides in this file.  */
+#undef sprintf
+
+/* my_strerror (errnum) is equivalent to strerror (errnum).
+   But it uses its own buffer, not the one from strerror().  */
+#define STATIC static
+#undef strerror
+#define strerror my_strerror
+#include "strerror-impl.h"
+
 void
 perror (const char *string)
 {
-  const char *errno_description = strerror (errno);
+  const char *errno_description = my_strerror (errno);
 
   if (string != NULL && *string != '\0')
     fprintf (stderr, "%s: %s\n", string, errno_description);
--- lib/strerror.c.orig Thu May 19 21:44:53 2011
+++ lib/strerror.c      Thu May 19 21:22:27 2011
@@ -32,26 +32,6 @@
 /* Use the system functions, not the gnulib overrides in this file.  */
 # undef sprintf
 
-char *
-strerror (int n)
-{
-  static char buf[256];
-
-  int ret = strerror_r (n, buf, sizeof (buf));
-
-  if (ret == 0)
-    return buf;
-
-  if (ret == ERANGE)
-    /* If this happens, increase the size of buf.  */
-    abort ();
-
-  {
-    static char const fmt[] = "Unknown error (%d)";
-    verify (sizeof (buf) >= sizeof (fmt) + INT_STRLEN_BOUND (n));
-    sprintf (buf, fmt, n);
-    return buf;
-  }
-}
+# include "strerror-impl.h"
 
 #endif
--- modules/perror.orig Thu May 19 21:44:53 2011
+++ modules/perror      Thu May 19 21:23:39 2011
@@ -3,12 +3,15 @@
 
 Files:
 lib/perror.c
+lib/strerror-impl.h
 m4/perror.m4
 
 Depends-on:
 stdio
-errno           [test $REPLACE_PERROR = 1]
-strerror        [test $REPLACE_PERROR = 1]
+errno            [test $REPLACE_PERROR = 1]
+intprops         [test $REPLACE_PERROR = 1]
+verify           [test $REPLACE_PERROR = 1]
+strerror_r-posix [test $REPLACE_PERROR = 1]
 
 configure.ac:
 gl_FUNC_PERROR
--- modules/strerror.orig       Thu May 19 21:44:53 2011
+++ modules/strerror    Thu May 19 21:19:22 2011
@@ -3,6 +3,7 @@
 
 Files:
 lib/strerror.c
+lib/strerror-impl.h
 m4/strerror.m4
 
 Depends-on:
-- 
In memoriam Anne Boleyn <http://en.wikipedia.org/wiki/Anne_Boleyn>

Reply via email to