From 74175b903b1716c1677658e45fa69ef1fbc99015 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Thu, 28 Apr 2011 16:46:16 -0600 Subject: [PATCH] getaddrinfo: fix gai_strerror signature Several platforms declare gai_strerror to return char* rather than const char*. Worse, on mingw, if UNICODE is defined, it is defined to return WCHAR*, which means the result is in unicode but an application expecting bytes for characters will only see a one-byte answer. * m4/getaddrinfo.m4 (gl_GETADDRINFO): Detect broken signatures, and work around mingw with UNICODE defined. (gl_PREREQ_GETADDRINFO): Drop redundant decl check. * m4/netdb_h.m4 (gl_NETDB_H_DEFAULTS): Add witness. * modules/netdb (Makefile.am): Substitute it. * lib/netdb.in.h (gai_strerror): Declare replacement. * lib/gai_strerror.c (rpl_gai_strerror): Fix signature. * doc/posix-functions/gai_strerror.texi (gai_strerror): Document the fix. Signed-off-by: Eric Blake --- ChangeLog | 11 +++++++++++ doc/posix-functions/gai_strerror.texi | 15 +++++++++----- lib/gai_strerror.c | 21 ++++++++++++++++++-- lib/netdb.in.h | 15 ++++++++++++-- m4/getaddrinfo.m4 | 37 ++++++++++++++++++++++++++--------- m4/netdb_h.m4 | 1 + modules/netdb | 1 + 7 files changed, 83 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6b755c147..9e5aa4155 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2011-04-28 Eric Blake + getaddrinfo: fix gai_strerror signature + * m4/getaddrinfo.m4 (gl_GETADDRINFO): Detect broken signatures, + and work around mingw with UNICODE defined. + (gl_PREREQ_GETADDRINFO): Drop redundant decl check. + * m4/netdb_h.m4 (gl_NETDB_H_DEFAULTS): Add witness. + * modules/netdb (Makefile.am): Substitute it. + * lib/netdb.in.h (gai_strerror): Declare replacement. + * lib/gai_strerror.c (rpl_gai_strerror): Fix signature. + * doc/posix-functions/gai_strerror.texi (gai_strerror): Document + the fix. + getsockopt: avoid compiler warning * lib/getsockopt.c (rpl_getsockopt): Add a cast for mingw. Reported by Matthias Bolte. diff --git a/doc/posix-functions/gai_strerror.texi b/doc/posix-functions/gai_strerror.texi index ece2bdc99..d94a6ed9b 100644 --- a/doc/posix-functions/gai_strerror.texi +++ b/doc/posix-functions/gai_strerror.texi @@ -10,13 +10,18 @@ Portability problems fixed by Gnulib: @itemize @item This function is missing on some platforms: -HP-UX 11.11, IRIX 6.5, OSF/1 4.0, Solaris 7, Cygwin 1.5.x, mingw, Interix 3.5, BeOS. +HP-UX 11.11, IRIX 6.5, OSF/1 4.0, Solaris 7, Cygwin 1.5.x, Interix +3.5, BeOS. +@item +This function is only available in @code{} on some +platforms: +mingw. +@item +This function's return type is @code{char *} instead of @code{const char *} +on some platforms: +AIX 7.1, HP-UX 11, OSF/1 5.1, Solaris 9, mingw. @end itemize Portability problems not fixed by Gnulib: @itemize -@item -This function's return type is @code{char *} instead of @code{const char *} -on some platforms: -AIX 7.1, HP-UX 11, OSF/1 5.1, Solaris 9. @end itemize diff --git a/lib/gai_strerror.c b/lib/gai_strerror.c index ee595e1a7..f758f8e90 100644 --- a/lib/gai_strerror.c +++ b/lib/gai_strerror.c @@ -32,6 +32,22 @@ # define N_(String) String #endif +#if HAVE_DECL_GAI_STRERROR + +# include +# undef gai_strerror +# if HAVE_DECL_GAI_STRERRORA +# define gai_strerror gai_strerrorA +# endif + +const char * +rpl_gai_strerror (int code) +{ + return gai_strerror (code); +} + +#else /* !HAVE_DECL_GAI_STRERROR */ + static struct { int code; @@ -71,6 +87,7 @@ gai_strerror (int code) return _("Unknown error"); } -#ifdef _LIBC +# ifdef _LIBC libc_hidden_def (gai_strerror) -#endif +# endif +#endif /* !HAVE_DECL_GAI_STRERROR */ diff --git a/lib/netdb.in.h b/lib/netdb.in.h index d789e3422..64cd9ac53 100644 --- a/lib/netdb.in.h +++ b/lib/netdb.in.h @@ -167,12 +167,23 @@ extern int getaddrinfo (const char *restrict nodename, extern void freeaddrinfo (struct addrinfo *ai) _GL_ARG_NONNULL ((1)); # endif -# if !@HAVE_DECL_GAI_STRERROR@ +# if @REPLACE_GAI_STRERROR@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef gai_strerror +# define gai_strerror rpl_gai_strerror +# endif +_GL_FUNCDECL_RPL (gai_strerror, const char *, (int ecode)); +_GL_CXXALIAS_RPL (gai_strerror, const char *, (int ecode)); +# else +# if !@HAVE_DECL_GAI_STRERROR@ /* Convert error return from getaddrinfo() to a string. For more details, see the POSIX:2001 specification . */ -extern const char *gai_strerror (int ecode); +_GL_FUNCDECL_SYS (gai_strerror, const char *, (int ecode)); +# endif +_GL_CXXALIAS_SYS (gai_strerror, const char *, (int ecode)); # endif +_GL_CXXALIASWARN (gai_strerror); # if !@HAVE_DECL_GETNAMEINFO@ /* Convert socket address to printable node and service names. diff --git a/m4/getaddrinfo.m4 b/m4/getaddrinfo.m4 index e57623694..f29e90398 100644 --- a/m4/getaddrinfo.m4 +++ b/m4/getaddrinfo.m4 @@ -1,4 +1,4 @@ -# getaddrinfo.m4 serial 24 +# getaddrinfo.m4 serial 25 dnl Copyright (C) 2004-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, @@ -62,9 +62,7 @@ AC_DEFUN([gl_GETADDRINFO], # We can't use AC_REPLACE_FUNCS here because gai_strerror may be an # inline function declared in ws2tcpip.h, so we need to get that # header included somehow. - AC_CACHE_CHECK([for gai_strerror (possibly via ws2tcpip.h)], - gl_cv_func_gai_strerror, [ - AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + AC_CHECK_DECLS([gai_strerror, gai_strerrorA], [], [break], [[ #include #ifdef HAVE_SYS_SOCKET_H #include @@ -76,11 +74,32 @@ AC_DEFUN([gl_GETADDRINFO], #include #endif #include -]], [[gai_strerror (NULL);]])], - [gl_cv_func_gai_strerror=yes], - [gl_cv_func_gai_strerror=no])]) - if test $gl_cv_func_gai_strerror = no; then +]]) + if test $ac_cv_have_decl_gai_strerror = no; then AC_LIBOBJ([gai_strerror]) + else + dnl check for correct signature + AC_CACHE_CHECK([for gai_strerror with POSIX signature], + [gl_cv_func_gai_strerror_posix_signature], [ + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_WS2TCPIP_H +#include +#endif +#include +extern const char *gai_strerror(int);]])], + [gl_cv_func_gai_strerror_posix_signature=yes], + [gl_cv_func_gai_strerror_posix_signature=no])]) + if test $gl_cv_func_gai_strerror_posix_signature = no; then + REPLACE_GAI_STRERROR=1 + AC_LIBOBJ([gai_strerror]) + fi fi LIBS="$gai_saved_LIBS" @@ -112,7 +131,7 @@ AC_DEFUN([gl_PREREQ_GETADDRINFO], [ AC_CHECK_HEADERS_ONCE([netinet/in.h]) - AC_CHECK_DECLS([getaddrinfo, freeaddrinfo, gai_strerror, getnameinfo],,,[ + AC_CHECK_DECLS([getaddrinfo, freeaddrinfo, getnameinfo],,,[ /* sys/types.h is not needed according to POSIX, but the sys/socket.h in i386-unknown-freebsd4.10 and powerpc-apple-darwin5.5 required it. */ diff --git a/m4/netdb_h.m4 b/m4/netdb_h.m4 index 9a01cd6a7..259c7a318 100644 --- a/m4/netdb_h.m4 +++ b/m4/netdb_h.m4 @@ -37,4 +37,5 @@ AC_DEFUN([gl_NETDB_H_DEFAULTS], HAVE_DECL_GAI_STRERROR=1; AC_SUBST([HAVE_DECL_GAI_STRERROR]) HAVE_DECL_GETADDRINFO=1; AC_SUBST([HAVE_DECL_GETADDRINFO]) HAVE_DECL_GETNAMEINFO=1; AC_SUBST([HAVE_DECL_GETNAMEINFO]) + REPLACE_GAI_STRERROR=0; AC_SUBST([REPLACE_GAI_STRERROR]) ]) diff --git a/modules/netdb b/modules/netdb index 97c40bcce..8d210c949 100644 --- a/modules/netdb +++ b/modules/netdb @@ -33,6 +33,7 @@ netdb.h: netdb.in.h $(top_builddir)/config.status $(ARG_NONNULL_H) $(WARN_ON_USE -e 's|@''HAVE_DECL_GAI_STRERROR''@|$(HAVE_DECL_GAI_STRERROR)|g' \ -e 's|@''HAVE_DECL_GETADDRINFO''@|$(HAVE_DECL_GETADDRINFO)|g' \ -e 's|@''HAVE_DECL_GETNAMEINFO''@|$(HAVE_DECL_GETNAMEINFO)|g' \ + -e 's|@''REPLACE_GAI_STRERROR''@|$(REPLACE_GAI_STRERROR)|g' \ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ < $(srcdir)/netdb.in.h; \ -- 2.11.0