]> Savannah Git Hosting - gnulib.git/commitdiff
getaddrinfo: Fix calling convention in 32-bit mode on native Windows.
authorBruno Haible <bruno@clisp.org>
Thu, 12 Dec 2019 01:43:07 +0000 (02:43 +0100)
committerBruno Haible <bruno@clisp.org>
Thu, 12 Dec 2019 01:43:07 +0000 (02:43 +0100)
* m4/getaddrinfo.m4 (gl_GETADDRINFO): Test whether getaddrinfo has a
non-POSIX signature. If so, set REPLACE_GETADDRINFO. Define
HAVE_GETADDRINFO as a C macro.
* lib/netdb.in.h (getaddrinfo, freeaddrinfo): If REPLACE_GETADDRINFO,
declare as replacement functions.
* lib/getaddrinfo.c (getaddrinfo, freeaddrinfo): If HAVE_GETADDRINFO,
define as no-op overrides.
* m4/netdb_h.m4 (gl_NETDB_H_DEFAULTS): Initialize REPLACE_GETADDRINFO.
* modules/netdb (Makefile.am): Substitute REPLACE_GETADDRINFO.
* modules/getaddrinfo (Depends-on, configure.ac): Test
REPLACE_GETADDRINFO.
* doc/posix-functions/getaddrinfo.texi: Mention calling convention
problem.
* doc/posix-functions/freeaddrinfo.texi: Mention header file and calling
convention problems.

ChangeLog
doc/posix-functions/freeaddrinfo.texi
doc/posix-functions/getaddrinfo.texi
lib/getaddrinfo.c
lib/netdb.in.h
m4/getaddrinfo.m4
m4/netdb_h.m4
modules/getaddrinfo
modules/netdb

index 963f1fb6797b52e27e12044591d6a7e1c2db7083..326c446e7781909c4ac41a819f8a903ea3d6d9b8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2019-12-11  Bruno Haible  <bruno@clisp.org>
+
+       getaddrinfo: Fix calling convention in 32-bit mode on native Windows.
+       * m4/getaddrinfo.m4 (gl_GETADDRINFO): Test whether getaddrinfo has a
+       non-POSIX signature. If so, set REPLACE_GETADDRINFO. Define
+       HAVE_GETADDRINFO as a C macro.
+       * lib/netdb.in.h (getaddrinfo, freeaddrinfo): If REPLACE_GETADDRINFO,
+       declare as replacement functions.
+       * lib/getaddrinfo.c (getaddrinfo, freeaddrinfo): If HAVE_GETADDRINFO,
+       define as no-op overrides.
+       * m4/netdb_h.m4 (gl_NETDB_H_DEFAULTS): Initialize REPLACE_GETADDRINFO.
+       * modules/netdb (Makefile.am): Substitute REPLACE_GETADDRINFO.
+       * modules/getaddrinfo (Depends-on, configure.ac): Test
+       REPLACE_GETADDRINFO.
+       * doc/posix-functions/getaddrinfo.texi: Mention calling convention
+       problem.
+       * doc/posix-functions/freeaddrinfo.texi: Mention header file and calling
+       convention problems.
+
 2019-12-11  Paul Eggert  <eggert@cs.ucla.edu>
 
        dfa: prefer signed integers for internals
index 4aa9af2e81788a44a482e47382f0e27de62637a3..8116571d6ca21b75c090af0058b8f0533b153a71 100644 (file)
@@ -11,6 +11,12 @@ Portability problems fixed by Gnulib:
 @item
 This function is missing on some platforms:
 HP-UX 11.11, IRIX 6.5, Cygwin 1.5.x, mingw, MSVC 14.
+@item
+On Windows, this function is declared in @code{<ws2tcpip.h>} rather than in
+@code{<netdb.h>}.
+@item
+On Windows, in 32-bit mode, this function is defined with a calling convention
+that is different from @code{cdecl}.
 @end itemize
 
 Portability problems not fixed by Gnulib:
index 1e4b2440a95448f937a81789874312ad0ff65073..eae5b8b593e062e1d66f3fd78a8b2f8c85b09929 100644 (file)
@@ -14,6 +14,9 @@ HP-UX 11.11, IRIX 6.5, Cygwin 1.5.x, mingw, MSVC 14.
 @item
 On Windows, this function is declared in @code{<ws2tcpip.h>} rather than in
 @code{<netdb.h>}.
+@item
+On Windows, in 32-bit mode, this function is defined with a calling convention
+that is different from @code{cdecl}.
 @end itemize
 
 Portability problems not fixed by Gnulib:
index 123a2b2cf1b3324ea64de24502f7801968e56f41..56cbe2b861c28e256211d8fab018a585a5d4d8d8 100644 (file)
 # define PF_UNSPEC 0
 #endif
 
-#if defined _WIN32 && !defined __CYGWIN__
-# define WINDOWS_NATIVE
-#endif
+#if HAVE_GETADDRINFO
+
+/* Override with cdecl calling convention.  */
+
+int
+getaddrinfo (const char *restrict nodename,
+             const char *restrict servname,
+             const struct addrinfo *restrict hints,
+             struct addrinfo **restrict res)
+# undef getaddrinfo
+{
+  return getaddrinfo (nodename, servname, hints, res);
+}
+
+void
+freeaddrinfo (struct addrinfo *ai)
+# undef freeaddrinfo
+{
+  freeaddrinfo (ai);
+}
+
+#else
+
+# if defined _WIN32 && !defined __CYGWIN__
+#  define WINDOWS_NATIVE
+# endif
 
 /* gl_sockets_startup */
-#include "sockets.h"
+# include "sockets.h"
 
-#ifdef WINDOWS_NATIVE
+# ifdef WINDOWS_NATIVE
 
 /* Avoid warnings from gcc -Wcast-function-type.  */
-# define GetProcAddress \
-   (void *) GetProcAddress
+#  define GetProcAddress \
+    (void *) GetProcAddress
 
 typedef int (WSAAPI *getaddrinfo_func) (const char*, const char*,
                                         const struct addrinfo*,
@@ -112,20 +135,20 @@ use_win32_p (void)
 
   return 1;
 }
-#endif
+# endif
 
 static bool
 validate_family (int family)
 {
   /* FIXME: Support more families. */
-#if HAVE_IPV4
+# if HAVE_IPV4
      if (family == PF_INET)
        return true;
-#endif
-#if HAVE_IPV6
+# endif
+# if HAVE_IPV6
      if (family == PF_INET6)
        return true;
-#endif
+# endif
      if (family == PF_UNSPEC)
        return true;
      return false;
@@ -144,23 +167,23 @@ getaddrinfo (const char *restrict nodename,
   struct hostent *he;
   void *storage;
   size_t size;
-#if HAVE_IPV6
+# if HAVE_IPV6
   struct v6_pair {
     struct addrinfo addrinfo;
     struct sockaddr_in6 sockaddr_in6;
   };
-#endif
-#if HAVE_IPV4
+# endif
+# if HAVE_IPV4
   struct v4_pair {
     struct addrinfo addrinfo;
     struct sockaddr_in sockaddr_in;
   };
-#endif
+# endif
 
-#ifdef WINDOWS_NATIVE
+# ifdef WINDOWS_NATIVE
   if (use_win32_p ())
     return getaddrinfo_ptr (nodename, servname, hints, res);
-#endif
+# endif
 
   if (hints && (hints->ai_flags & ~(AI_CANONNAME|AI_PASSIVE)))
     /* FIXME: Support more flags. */
@@ -179,11 +202,11 @@ getaddrinfo (const char *restrict nodename,
       if (!(hints->ai_flags & AI_PASSIVE))
         return EAI_NONAME;
 
-#ifdef HAVE_IPV6
+# ifdef HAVE_IPV6
       nodename = (hints->ai_family == AF_INET6) ? "::" : "0.0.0.0";
-#else
+# else
       nodename = "0.0.0.0";
-#endif
+# endif
     }
 
   if (servname)
@@ -217,17 +240,17 @@ getaddrinfo (const char *restrict nodename,
 
   switch (he->h_addrtype)
     {
-#if HAVE_IPV6
+# if HAVE_IPV6
     case PF_INET6:
       size = sizeof (struct v6_pair);
       break;
-#endif
+# endif
 
-#if HAVE_IPV4
+# if HAVE_IPV4
     case PF_INET:
       size = sizeof (struct v4_pair);
       break;
-#endif
+# endif
 
     default:
       return EAI_NODATA;
@@ -239,7 +262,7 @@ getaddrinfo (const char *restrict nodename,
 
   switch (he->h_addrtype)
     {
-#if HAVE_IPV6
+# if HAVE_IPV6
     case PF_INET6:
       {
         struct v6_pair *p = storage;
@@ -261,9 +284,9 @@ getaddrinfo (const char *restrict nodename,
         tmp->ai_addrlen = sizeof *sinp;
       }
       break;
-#endif
+# endif
 
-#if HAVE_IPV4
+# if HAVE_IPV4
     case PF_INET:
       {
         struct v4_pair *p = storage;
@@ -285,7 +308,7 @@ getaddrinfo (const char *restrict nodename,
         tmp->ai_addrlen = sizeof *sinp;
       }
       break;
-#endif
+# endif
 
     default:
       free (storage);
@@ -313,21 +336,21 @@ getaddrinfo (const char *restrict nodename,
   tmp->ai_addr->sa_family = he->h_addrtype;
   tmp->ai_family = he->h_addrtype;
 
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+# ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
   switch (he->h_addrtype)
     {
-#if HAVE_IPV4
+#  if HAVE_IPV4
     case AF_INET:
       tmp->ai_addr->sa_len = sizeof (struct sockaddr_in);
       break;
-#endif
-#if HAVE_IPV6
+#  endif
+#  if HAVE_IPV6
     case AF_INET6:
       tmp->ai_addr->sa_len = sizeof (struct sockaddr_in6);
       break;
-#endif
+#  endif
     }
-#endif
+# endif
 
   /* FIXME: If more than one address, create linked list of addrinfo's. */
 
@@ -340,13 +363,13 @@ getaddrinfo (const char *restrict nodename,
 void
 freeaddrinfo (struct addrinfo *ai)
 {
-#ifdef WINDOWS_NATIVE
+# ifdef WINDOWS_NATIVE
   if (use_win32_p ())
     {
       freeaddrinfo_ptr (ai);
       return;
     }
-#endif
+# endif
 
   while (ai)
     {
@@ -366,11 +389,11 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
              char *restrict service, socklen_t servicelen,
              int flags)
 {
-#ifdef WINDOWS_NATIVE
+# ifdef WINDOWS_NATIVE
   if (use_win32_p ())
     return getnameinfo_ptr (sa, salen, node, nodelen,
                             service, servicelen, flags);
-#endif
+# endif
 
   /* FIXME: Support other flags. */
   if ((node && nodelen > 0 && !(flags & NI_NUMERICHOST)) ||
@@ -383,18 +406,18 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
 
   switch (sa->sa_family)
     {
-#if HAVE_IPV4
+# if HAVE_IPV4
     case AF_INET:
       if (salen < sizeof (struct sockaddr_in))
         return EAI_FAMILY;
       break;
-#endif
-#if HAVE_IPV6
+# endif
+# if HAVE_IPV6
     case AF_INET6:
       if (salen < sizeof (struct sockaddr_in6))
         return EAI_FAMILY;
       break;
-#endif
+# endif
     default:
       return EAI_FAMILY;
     }
@@ -403,23 +426,23 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
     {
       switch (sa->sa_family)
         {
-#if HAVE_IPV4
+# if HAVE_IPV4
         case AF_INET:
           if (!inet_ntop (AF_INET,
                           &(((const struct sockaddr_in *) sa)->sin_addr),
                           node, nodelen))
             return EAI_SYSTEM;
           break;
-#endif
+# endif
 
-#if HAVE_IPV6
+# if HAVE_IPV6
         case AF_INET6:
           if (!inet_ntop (AF_INET6,
                           &(((const struct sockaddr_in6 *) sa)->sin6_addr),
                           node, nodelen))
             return EAI_SYSTEM;
           break;
-#endif
+# endif
 
         default:
           return EAI_FAMILY;
@@ -429,12 +452,12 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
   if (service && servicelen > 0 && flags & NI_NUMERICSERV)
     switch (sa->sa_family)
       {
-#if HAVE_IPV4
+# if HAVE_IPV4
       case AF_INET:
-#endif
-#if HAVE_IPV6
+# endif
+# if HAVE_IPV6
       case AF_INET6:
-#endif
+# endif
         {
           unsigned short int port
             = ntohs (((const struct sockaddr_in *) sa)->sin_port);
@@ -446,3 +469,5 @@ getnameinfo (const struct sockaddr *restrict sa, socklen_t salen,
 
   return 0;
 }
+
+#endif
index 80134655debd5cde95722daf7c17ea9ac61fa94d..d5078de8b16d46bacccca8473e6dca464aea1aa1 100644 (file)
@@ -158,33 +158,61 @@ struct addrinfo
 #  endif
 # endif
 
-# if !@HAVE_DECL_GETADDRINFO@
 /* Translate name of a service location and/or a service name to set of
    socket addresses.
    For more details, see the POSIX:2008 specification
    <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html>.  */
+# if @REPLACE_GETADDRINFO@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef getaddrinfo
+#   define getaddrinfo rpl_getaddrinfo
+#  endif
+_GL_FUNCDECL_RPL (getaddrinfo, int,
+                  (const char *restrict nodename,
+                   const char *restrict servname,
+                   const struct addrinfo *restrict hints,
+                   struct addrinfo **restrict res)
+                  _GL_ARG_NONNULL ((4)));
+_GL_CXXALIAS_RPL (getaddrinfo, int,
+                  (const char *restrict nodename,
+                   const char *restrict servname,
+                   const struct addrinfo *restrict hints,
+                   struct addrinfo **restrict res));
+# else
+#  if !@HAVE_DECL_GETADDRINFO@
 _GL_FUNCDECL_SYS (getaddrinfo, int,
                   (const char *restrict nodename,
                    const char *restrict servname,
                    const struct addrinfo *restrict hints,
                    struct addrinfo **restrict res)
                   _GL_ARG_NONNULL ((4)));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (getaddrinfo, int,
                   (const char *restrict nodename,
                    const char *restrict servname,
                    const struct addrinfo *restrict hints,
                    struct addrinfo **restrict res));
+# endif
 _GL_CXXALIASWARN (getaddrinfo);
 
-# if !@HAVE_DECL_FREEADDRINFO@
 /* Free 'addrinfo' structure AI including associated storage.
    For more details, see the POSIX:2008 specification
    <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html>.  */
+# if @REPLACE_GETADDRINFO@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef freeaddrinfo
+#   define freeaddrinfo rpl_freeaddrinfo
+#  endif
+_GL_FUNCDECL_RPL (freeaddrinfo, void, (struct addrinfo *ai)
+                                      _GL_ARG_NONNULL ((1)));
+_GL_CXXALIAS_RPL (freeaddrinfo, void, (struct addrinfo *ai));
+# else
+#  if !@HAVE_DECL_FREEADDRINFO@
 _GL_FUNCDECL_SYS (freeaddrinfo, void, (struct addrinfo *ai)
                                       _GL_ARG_NONNULL ((1)));
-# endif
+#  endif
 _GL_CXXALIAS_SYS (freeaddrinfo, void, (struct addrinfo *ai));
+# endif
 _GL_CXXALIASWARN (freeaddrinfo);
 
 # if @REPLACE_GAI_STRERROR@
index 59b8571e58e626a5cca28eb44971a0dd830e615c..d1d01bf968c7b8ea595a9a3a7ceb92cfdca726b0 100644 (file)
@@ -1,4 +1,4 @@
-# getaddrinfo.m4 serial 31
+# getaddrinfo.m4 serial 32
 dnl Copyright (C) 2004-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -55,10 +55,40 @@ AC_DEFUN([gl_GETADDRINFO],
     if test "$gl_cv_w32_getaddrinfo" = "yes"; then
       GETADDRINFO_LIB="-lws2_32"
       LIBS="$gai_saved_LIBS $GETADDRINFO_LIB"
+      dnl Check for correct signature, in particular for a cdecl-compatible
+      dnl calling convention.
+      AC_CACHE_CHECK([for getaddrinfo with POSIX signature],
+        [gl_cv_func_getaddrinfo_posix_signature],
+        [AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+#include <stddef.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+int getaddrinfo (const char *, const char *, const struct addrinfo *, struct addrinfo **);
+]])],
+           [gl_cv_func_getaddrinfo_posix_signature=yes],
+           [gl_cv_func_getaddrinfo_posix_signature=no])
+        ])
+      if test $gl_cv_func_getaddrinfo_posix_signature = no; then
+        REPLACE_GETADDRINFO=1
+      fi
     else
       HAVE_GETADDRINFO=0
     fi
   fi
+  AC_DEFINE_UNQUOTED([HAVE_GETADDRINFO], [$HAVE_GETADDRINFO],
+    [Define to 1 if getaddrinfo exists, or to 0 otherwise.])
 
   # 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
index 498c566ffb7e5bc4e4220450bb59cafcd29060ca..cb762c67905e658b4d2fc6a36331b27c81e9c0a8 100644 (file)
@@ -1,4 +1,4 @@
-# netdb_h.m4 serial 11
+# netdb_h.m4 serial 12
 dnl Copyright (C) 2008-2019 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -40,4 +40,5 @@ AC_DEFUN([gl_NETDB_H_DEFAULTS],
   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])
+  REPLACE_GETADDRINFO=0;    AC_SUBST([REPLACE_GETADDRINFO])
 ])
index 195a24afd8da0e981738882361c95a62921e24e8..490838a8af52c1365ec819417da14c4ef9f3703c 100644 (file)
@@ -10,18 +10,18 @@ Depends-on:
 netdb
 sys_socket
 extensions
-gettext-h       [test $HAVE_GETADDRINFO = 0 || test $HAVE_DECL_GAI_STRERROR = 0 || test $REPLACE_GAI_STRERROR = 1]
-inet_ntop       [test $HAVE_GETADDRINFO = 0]
-snprintf        [test $HAVE_GETADDRINFO = 0]
-stdbool         [test $HAVE_GETADDRINFO = 0]
-strdup          [test $HAVE_GETADDRINFO = 0]
-servent         [test $HAVE_GETADDRINFO = 0]
-hostent         [test $HAVE_GETADDRINFO = 0]
-sockets         [test $HAVE_GETADDRINFO = 0]
+gettext-h       [test $HAVE_GETADDRINFO = 0 || test $REPLACE_GETADDRINFO = 1 || test $HAVE_DECL_GAI_STRERROR = 0 || test $REPLACE_GAI_STRERROR = 1]
+inet_ntop       [test $HAVE_GETADDRINFO = 0 || test $REPLACE_GETADDRINFO = 1]
+snprintf        [test $HAVE_GETADDRINFO = 0 || test $REPLACE_GETADDRINFO = 1]
+stdbool         [test $HAVE_GETADDRINFO = 0 || test $REPLACE_GETADDRINFO = 1]
+strdup          [test $HAVE_GETADDRINFO = 0 || test $REPLACE_GETADDRINFO = 1]
+servent         [test $HAVE_GETADDRINFO = 0 || test $REPLACE_GETADDRINFO = 1]
+hostent         [test $HAVE_GETADDRINFO = 0 || test $REPLACE_GETADDRINFO = 1]
+sockets         [test $HAVE_GETADDRINFO = 0 || test $REPLACE_GETADDRINFO = 1]
 
 configure.ac:
 gl_GETADDRINFO
-if test $HAVE_GETADDRINFO = 0; then
+if test $HAVE_GETADDRINFO = 0 || test $REPLACE_GETADDRINFO = 1; then
   AC_LIBOBJ([getaddrinfo])
 fi
 if test $HAVE_DECL_GAI_STRERROR = 0 || test $REPLACE_GAI_STRERROR = 1; then
index b324866c1b152262c220173e84ee6e4b911b484d..89408fa9194d9ba83f08069d0b4607424260ad44 100644 (file)
@@ -36,6 +36,7 @@ netdb.h: netdb.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
              -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 's|@''REPLACE_GETADDRINFO''@|$(REPLACE_GETADDRINFO)|g' \
              -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
              -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
              -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \