Mercurial > hg > octave-kai > gnulib-hg
changeset 14765:8e23facf1d9e
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.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Thu, 19 May 2011 20:57:21 +0200 |
parents | 2b72df632b91 |
children | 3618a75b519d |
files | ChangeLog lib/strerror_r.c m4/strerror_r.m4 |
diffstat | 3 files changed, 128 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-05-19 Bruno Haible <bruno@clisp.org> + + 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. + 2011-05-19 Bruno Haible <bruno@clisp.org> strerror_r: Fix test failure on mingw.
--- a/lib/strerror_r.c +++ b/lib/strerror_r.c @@ -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;
--- a/m4/strerror_r.m4 +++ b/m4/strerror_r.m4 @@ -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]) : ])