From: Guy Harris Date: Tue, 19 Mar 2019 08:41:03 +0000 (-0700) Subject: Make sure asprintf() is declared if it's present. X-Git-Tag: libpcap-1.10-bp~518 X-Git-Url: https://git.tcpdump.org/libpcap/commitdiff_plain/5710ec495d98d89d3a7c0722786081fee908b43e Make sure asprintf() is declared if it's present. GNU libc is a pain. If you don't define _GNU_SOURCE, it doesn't declare asprintf(). If you *do* define _GNU_SOURCE, the strerror_r() it declares isn't POSIX-compliant. We use asprintf() if present, so we need it to be declared; define _GNU_SOURCE in ftmacros.h. At configuration time, if we have strerror_r(), check whether it's GNU-style or POSIX-style, and define different #defines for those two cases. Handle GNU-style strerror_r() and POSIX-style strerror_r() differently in pcap_fmt_errmsg_for_errno(). Make sure everything that uses asprintf() includes ftmacros.h before including stdio.h. --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 27ced43b..e6a0c9ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -335,7 +335,34 @@ endif(NOT WIN32) # check_function_exists(strerror HAVE_STRERROR) check_function_exists(strerror_r HAVE_STRERROR_R) -check_function_exists(strerror_s HAVE_STRERROR_S) +if(HAVE_STRERROR_R) + # + # We have strerror_r; if we define _GNU_SOURCE, is it a + # POSIX-compliant strerror_r() or a GNU strerror_r()? + # + check_c_source_compiles( +"#define _GNU_SOURCE +#include + +/* Define it GNU-style; that will cause an error if it's not GNU-style */ +extern char *strerror_r(int, char *, size_t); + +int +main(void) +{ + return 0; +} +" + HAVE_GNU_STRERROR_R) + if(NOT HAVE_GNU_STRERROR_R) + set(HAVE_POSIX_STRERROR_R YES) + endif(NOT HAVE_GNU_STRERROR_R) +else(HAVE_STRERROR_R) + # + # We don't have strerror_r; do we have strerror_s? + # + check_function_exists(strerror_s HAVE_STRERROR_S) +endif(HAVE_STRERROR_R) check_function_exists(strlcpy HAVE_STRLCPY) check_function_exists(strlcat HAVE_STRLCAT) check_function_exists(snprintf HAVE_SNPRINTF) diff --git a/cmakeconfig.h.in b/cmakeconfig.h.in index 0d963df5..64723979 100644 --- a/cmakeconfig.h.in +++ b/cmakeconfig.h.in @@ -54,6 +54,9 @@ /* Define to 1 if you have the `getspnam' function. */ #cmakedefine HAVE_GETSPNAM 1 +/* Define to 1 if you have a GNU-style `strerror_r' function. */ +#cmakedefine HAVE_GNU_STRERROR_R 1 + /* on HP-UX 10.20 or later */ #cmakedefine HAVE_HPUX10_20_OR_LATER 1 @@ -147,6 +150,9 @@ /* Define to 1 if Packet32 API (WinPcap NPF driver) is available */ #cmakedefine HAVE_PACKET32 1 +/* Define to 1 if you have a POSIX-style `strerror_r' function. */ +#cmakedefine HAVE_POSIX_STRERROR_R 1 + /* define if net/pfvar.h defines PF_NAT through PF_NORDR */ #cmakedefine HAVE_PF_NAT_THROUGH_PF_NORDR 1 @@ -180,9 +186,6 @@ /* Define to 1 if you have the `strerror' function. */ #cmakedefine HAVE_STRERROR 1 -/* Define to 1 if you have the `strerror_r' function. */ -#cmakedefine HAVE_STRERROR_R 1 - /* Define to 1 if you have the `strerror_s' function. */ #cmakedefine HAVE_STRERROR_S 1 diff --git a/config.h.in b/config.h.in index b08657fe..b7ca36c7 100644 --- a/config.h.in +++ b/config.h.in @@ -60,6 +60,9 @@ /* Define to 1 if you have the `getspnam' function. */ #undef HAVE_GETSPNAM +/* Define to 1 if you have a GNU-style `strerror_r' function. */ +#undef HAVE_GNU_STRERROR_R + /* on HP-UX 10.20 or later */ #undef HAVE_HPUX10_20_OR_LATER @@ -165,6 +168,9 @@ /* define if net/pfvar.h defines PF_NAT through PF_NORDR */ #undef HAVE_PF_NAT_THROUGH_PF_NORDR +/* Define to 1 if you have a POSIX-style `strerror_r' function. */ +#undef HAVE_POSIX_STRERROR_R + /* Define to 1 if you have the header file. */ #undef HAVE_RTE_BUS_H @@ -198,9 +204,6 @@ /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR -/* Define to 1 if you have the `strerror_r' function. */ -#undef HAVE_STRERROR_R - /* Define to 1 if you have the `strerror_s' function. */ #undef HAVE_STRERROR_S diff --git a/configure b/configure index 553f138c..b4bcfbba 100755 --- a/configure +++ b/configure @@ -5340,19 +5340,83 @@ $as_echo "$ac_cv_lbl_gcc_fixincludes" >&6; } fi fi -for ac_func in strerror strerror_r strerror_s +for ac_func in strerror do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror" +if test "x$ac_cv_func_strerror" = xyes; then : cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +#define HAVE_STRERROR 1 +_ACEOF + +fi +done + +ac_fn_c_check_func "$LINENO" "strerror_r" "ac_cv_func_strerror_r" +if test "x$ac_cv_func_strerror_r" = xyes; then : + + # + # We have strerror_r; if we define _GNU_SOURCE, is it a + # POSIX-compliant strerror_r() or a GNU strerror_r()? + # + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strerror_r is GNU-style" >&5 +$as_echo_n "checking whether strerror_r is GNU-style... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #define _GNU_SOURCE +#include + +/* Define it GNU-style; that will cause an error if it's not GNU-style */ +extern char *strerror_r(int, char *, size_t); + +int +main(void) +{ + return 0; +} + + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + # GNU-style + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define HAVE_GNU_STRERROR_R /**/" >>confdefs.h + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +$as_echo "#define HAVE_POSIX_STRERROR_R /**/" >>confdefs.h + + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +else + + # + # We don't have strerror_r; do we have strerror_s? + # + for ac_func in strerror_s +do : + ac_fn_c_check_func "$LINENO" "strerror_s" "ac_cv_func_strerror_s" +if test "x$ac_cv_func_strerror_s" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRERROR_S 1 _ACEOF fi done +fi + + # # Thanks, IBM, for not providing vsyslog() in AIX! # diff --git a/configure.ac b/configure.ac index efffe4d7..91efafc5 100644 --- a/configure.ac +++ b/configure.ac @@ -110,7 +110,48 @@ esac AC_LBL_FIXINCLUDES -AC_CHECK_FUNCS(strerror strerror_r strerror_s) +AC_CHECK_FUNCS(strerror) +AC_CHECK_FUNC(strerror_r, + [ + # + # We have strerror_r; if we define _GNU_SOURCE, is it a + # POSIX-compliant strerror_r() or a GNU strerror_r()? + # + AC_MSG_CHECKING(whether strerror_r is GNU-style) + AC_COMPILE_IFELSE( + [ + AC_LANG_SOURCE( +#define _GNU_SOURCE +#include + +/* Define it GNU-style; that will cause an error if it's not GNU-style */ +extern char *strerror_r(int, char *, size_t); + +int +main(void) +{ + return 0; +} +) + ], + [ + # GNU-style + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_GNU_STRERROR_R,, + [Define to 1 if you have a GNU-style `strerror_r' function.]) + ], + [ + AC_MSG_RESULT(no) + AC_DEFINE(HAVE_POSIX_STRERROR_R,, + [Define to 1 if you have a POSIX-style `strerror_r' function.]) + ]) + ], + [ + # + # We don't have strerror_r; do we have strerror_s? + # + AC_CHECK_FUNCS(strerror_s) + ]) # # Thanks, IBM, for not providing vsyslog() in AIX! diff --git a/fmtutils.c b/fmtutils.c index 0c527453..d01dc3e2 100644 --- a/fmtutils.c +++ b/fmtutils.c @@ -65,11 +65,6 @@ pcap_fmt_errmsg_for_errno(char *errbuf, size_t errbuflen, int errnum, size_t msglen; char *p; size_t errbuflen_remaining; -#if defined(HAVE_STRERROR_S) - errno_t err; -#elif defined(HAVE_STRERROR_R) - int err; -#endif va_start(ap, fmt); pcap_vsnprintf(errbuf, errbuflen, fmt, ap); @@ -96,7 +91,10 @@ pcap_fmt_errmsg_for_errno(char *errbuf, size_t errbuflen, int errnum, * Now append the string for the error code. */ #if defined(HAVE_STRERROR_S) - err = strerror_s(p, errbuflen_remaining, errnum); + /* + * We have a Windows-style strerror_s(). + */ + errno_t err = strerror_s(p, errbuflen_remaining, errnum); if (err != 0) { /* * It doesn't appear to be documented anywhere obvious @@ -104,8 +102,24 @@ pcap_fmt_errmsg_for_errno(char *errbuf, size_t errbuflen, int errnum, */ pcap_snprintf(p, errbuflen_remaining, "Error %d", errnum); } -#elif defined(HAVE_STRERROR_R) - err = strerror_r(errnum, p, errbuflen_remaining); +#elif defined(HAVE_GNU_STRERROR_R) + /* + * We have a GNU-style strerror_r(), which is *not* guaranteed to + * do anything to the buffer handed to it, and which returns a + * pointer to the error string, which may or may not be in + * the buffer. + * + * It is, however, guaranteed to succeed. + */ + char strerror_buf[PCAP_ERRBUF_SIZE]; + char *errstring = strerror_r(errnum, strerror_buf, PCAP_ERRBUF_SIZE); + pcap_snprintf(p, errbuflen_remaining, "%s", errstring); +#elif defined(HAVE_POSIX_STRERROR_R) + /* + * We have a POSIX-style strerror_r(), which is guaranteed to fill + * in the buffer, but is not guaranteed to succeed. + */ + int err = strerror_r(errnum, p, errbuflen_remaining); if (err == EINVAL) { /* * UNIX 03 says this isn't guaranteed to produce a diff --git a/ftmacros.h b/ftmacros.h index de8da98e..cd3daebd 100644 --- a/ftmacros.h +++ b/ftmacros.h @@ -85,20 +85,14 @@ */ #elif defined(__linux__) || defined(linux) || defined(__linux) /* - * We can't turn _GNU_SOURCE on because some versions of GNU Libc - * will give the GNU version of strerror_r(), which returns a - * string pointer and doesn't necessarily fill in the buffer, - * rather than the standard version of strerror_r(), which - * returns 0 or an errno and always fills in the buffer. We - * require both of the latter behaviors. + * Turn on _GNU_SOURCE to get everything GNU libc has to offer, + * including asprintf(). * - * So we try turning everything else on that we can. This includes - * defining _XOPEN_SOURCE as 600, because we want to force crypt() - * to be declared on systems that use GNU libc, such as most Linux - * distributions. + * Unfortunately, one thing it has to offer is a strerror_r() + * that's not POSIX-compliant, but we deal with that in + * pcap_fmt_errmsg_for_errno(). */ - #define _POSIX_C_SOURCE 200809L - #define _XOPEN_SOURCE 600 + #define _GNU_SOURCE /* * We turn on both _DEFAULT_SOURCE and _BSD_SOURCE to try to get diff --git a/pcap-new.c b/pcap-new.c index 6b333e4e..2cce433c 100644 --- a/pcap-new.c +++ b/pcap-new.c @@ -35,6 +35,8 @@ #include #endif +#include "ftmacros.h" + /* * sockutils.h may include on Windows, and pcap-int.h will * include portability.h, and portability.h, on Windows, expects that