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: Thu, 19 May 2011 20:58:35 +0200
User-agent: KMail/1.9.9

> >   1) The strerror_r replacement, when EXTEND_STRERROR_R is defined,
> >      clobbers the strerror function's buffer, which it shouldn't.

Here's a followup that tries harder to clobber the strerror function's
buffer. It still is not possible on Solaris <= 9 in 64-bit mode, because
that libc does not export 'sys_nerr'.


2011-05-19  Bruno Haible  <address@hidden>

        strerror_r: Avoid clobbering the strerror buffer when possible.
        * lib/strerror.c: Define _NETBSD_SOURCE. Include <nl_types.h>.
        (sys_nerr, sys_errlist): New declarations.
        (strerror_r): Be careful not to clobber the strerror buffer on NetBSD,
        HP-UX, native Win32, IRIX, and 32-bit Solaris.
        * m4/strerror_r.m4 (gl_PREREQ_STRERROR_R): Test whether catgets exists.

--- lib/strerror_r.c.orig       Thu May 19 20:50:20 2011
+++ lib/strerror_r.c    Thu May 19 20:49:54 2011
@@ -19,6 +19,9 @@
 
 #include <config.h>
 
+/* Enable declaration of sys_nerr and sys_errlist in <errno.h> on NetBSD.  */
+#define _NETBSD_SOURCE 1
+
 /* Specification.  */
 #include <string.h>
 
@@ -46,17 +49,45 @@
 
 #else /* (__GLIBC__ >= 2 || defined __UCLIBC__ ? !HAVE___XPG_STRERROR_R : 
!HAVE_DECL_STRERROR_R) */
 
-# include "glthread/lock.h"
-
-/* Use strerror(), with locking.  */
+/* Use the system's strerror().  */
 # undef strerror
 
 # define USE_SYSTEM_STRERROR 1
 
+# if defined __NetBSD__ || defined __hpux || ((defined _WIN32 || defined 
__WIN32__) && !defined __CYGWIN__) || defined __sgi || (defined __sun && 
!defined _LP64)
+
+/* No locking needed.  */
+
+/* Get catgets internationalization functions.  */
+#  if HAVE_CATGETS
+#   include <nl_types.h>
+#  endif
+
+/* Get sys_nerr, sys_errlist on HP-UX (otherwise only declared in C++ mode).
+   Get sys_nerr, sys_errlist on IRIX (otherwise only declared with _SGIAPI).  
*/
+#  if defined __hpux || defined __sgi
+extern int sys_nerr;
+extern char *sys_errlist[];
+#  endif
+
+/* Get sys_nerr on Solaris.  */
+#  if defined __sun && !defined _LP64
+extern int sys_nerr;
+#  endif
+
+/* Get sys_nerr, sys_errlist on native Windows.  */
+#  include <stdlib.h>
+
+# else
+
+#  include "glthread/lock.h"
+
 /* This lock protects the buffer returned by strerror().  We assume that
    no other uses of strerror() exist in the program.  */
 gl_lock_define_initialized(static, strerror_lock)
 
+# endif
+
 #endif
 
 
@@ -476,6 +507,87 @@
 
 #else /* USE_SYSTEM_STRERROR */
 
+    /* Try to do what strerror (errnum) does, but without clobbering the
+       buffer used by strerror().  */
+
+# if defined __NetBSD__ || defined __hpux || ((defined _WIN32 || defined 
__WIN32__) && !defined __CYGWIN__) /* NetBSD, HP-UX, native Win32 */
+
+    /* NetBSD:        sys_nerr, sys_errlist are declared through _NETBSD_SOURCE
+                      and <errno.h> above.
+       HP-UX:         sys_nerr, sys_errlist are declared explicitly above.
+       native Win32:  sys_nerr, sys_errlist are declared in <stdlib.h>.  */
+    if (errnum >= 0 && errnum < sys_nerr)
+      {
+#  if HAVE_CATGETS && (defined __NetBSD__ || defined __hpux)
+        int saved_errno = errno;
+#   if defined __NetBSD__
+        nl_catd catd = catopen ("libc", NL_CAT_LOCALE);
+        const char *errmsg =
+          (catd != (nl_catd)-1
+           ? catgets (catd, 1, errnum, sys_errlist[errnum])
+           : sys_errlist[errnum]);
+#   endif
+#   if defined __hpux
+        nl_catd catd = catopen ("perror", NL_CAT_LOCALE);
+        const char *errmsg =
+          (catd != (nl_catd)-1
+           ? catgets (catd, 1, 1 + errnum, sys_errlist[errnum])
+           : sys_errlist[errnum]);
+#   endif
+#  else
+        const char *errmsg = sys_errlist[errnum];
+#  endif
+        if (errmsg == NULL || *errmsg == '\0')
+          ret = EINVAL;
+        else
+          {
+            size_t len = strlen (errmsg);
+
+            if (len < buflen)
+              {
+                memcpy (buf, errmsg, len + 1);
+                ret = 0;
+              }
+            else
+              ret = ERANGE;
+          }
+#  if HAVE_CATGETS && (defined __NetBSD__ || defined __hpux)
+        if (catd != (nl_catd)-1)
+          catclose (catd);
+        errno = saved_errno;
+#  endif
+      }
+    else
+      ret = EINVAL;
+
+# elif defined __sgi || (defined __sun && !defined _LP64) /* IRIX, Solaris <= 
9 32-bit */
+
+    /* For a valid error number, the system's strerror() function returns
+       a pointer to a not copied string, not to a buffer.  */
+    if (errnum >= 0 && errnum < sys_nerr)
+      {
+        char *errmsg = strerror (errnum);
+
+        if (errmsg == NULL || *errmsg == '\0')
+          ret = EINVAL;
+        else
+          {
+            size_t len = strlen (errmsg);
+
+            if (len < buflen)
+              {
+                memcpy (buf, errmsg, len + 1);
+                ret = 0;
+              }
+            else
+              ret = ERANGE;
+          }
+      }
+    else
+      ret = EINVAL;
+
+# else
+
     gl_lock_lock (strerror_lock);
 
     {
@@ -502,6 +614,8 @@
 
     gl_lock_unlock (strerror_lock);
 
+# endif
+
 #endif
 
     return ret;
--- m4/strerror_r.m4.orig       Thu May 19 20:50:20 2011
+++ m4/strerror_r.m4    Thu May 19 20:48:10 2011
@@ -1,4 +1,4 @@
-# strerror_r.m4 serial 5
+# strerror_r.m4 serial 6
 dnl Copyright (C) 2002, 2007-2011 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -103,5 +103,6 @@
 
 # Prerequisites of lib/strerror_r.c.
 AC_DEFUN([gl_PREREQ_STRERROR_R], [
+  AC_CHECK_FUNCS_ONCE([catgets])
   :
 ])

-- 
In memoriam Anne Boleyn <http://en.wikipedia.org/wiki/Anne_Boleyn>



reply via email to

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