Skip to content

Commit

Permalink
macOS: Fix crash on OS X 10.8 caused by missing connectx function
Browse files Browse the repository at this point in the history
The connectx() function call appeared in Darwin 15.0.0.
That covers OS X 10.11, iOS 9 and tvOS 9.

Because connectx is not declared with weak_import attribute it's not
possible to build libcurl on OS X 10.11 and later and target systems
which don't have _connectx symbol declared in libsystem_kernel.dylib
(i.e. OS X 10.8 and earlier).

Solution is to use connectx only on platforms that officially support it
i.e. by defining CFLAGS="-mmacosx-version-min=10.11" in configure step.

Note: It is possible to conditionally use connectx() in libcurl
targeting range of systems based on availability determined during
runtime using dlsym().

Fixes curl#1330
Closes curl#1336
  • Loading branch information
markovicpp authored and jay committed Oct 2, 2017
1 parent 440dbcb commit f28aac9
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 21 deletions.
18 changes: 18 additions & 0 deletions CMake/CurlTests.c
Original file line number Diff line number Diff line change
Expand Up @@ -549,3 +549,21 @@ main() {
return 0;
}
#endif
#ifdef HAVE_VALID_CONNECTX
# include <Availability.h>
# include <sys/socket.h>
# if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
# if (__MAC_OS_X_VERSION_MIN_REQUIRED < 101100)
# error Function requires deployment target OS X 10.11 or later
# endif
# elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
# if (__IPHONE_OS_VERSION_MIN_REQUIRED < 90000)
# error Function requires deployment target iOS 9.0 or later
# endif
# endif

main() {
connectx(0, 0, 0, 0, 0, 0, 0, 0);
return 0;
}
#endif
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,15 @@ check_symbol_exists(fcntl "${CURL_INCLUDES}" HAVE_FCNTL)
check_symbol_exists(ioctl "${CURL_INCLUDES}" HAVE_IOCTL)
check_symbol_exists(setsockopt "${CURL_INCLUDES}" HAVE_SETSOCKOPT)

# The connectx() function call appeared in Darwin 15.0.0
# but it's not declared using availability attribute.
# Additionally _connectx symbol is part of OS X 10.9/10.10
# system lib but does not have specified functionality.
check_symbol_exists(connectx "${CURL_INCLUDES}" HAVE_CONNECTX)
if(HAVE_CONNECTX)
curl_internal_test_run(HAVE_VALID_CONNECTX)
endif(HAVE_CONNECTX)

# symbol exists in win32, but function does not.
if(WIN32)
if(ENABLE_INET_PTON)
Expand Down
40 changes: 40 additions & 0 deletions acinclude.m4
Original file line number Diff line number Diff line change
Expand Up @@ -2970,3 +2970,43 @@ AC_DEFUN([CURL_SUPPORTS_BUILTIN_AVAILABLE], [
AC_MSG_RESULT([no])
])
])


dnl CURL_CHECK_FUNC_CONNECTX
dnl
dnl Check if connectx() function is present.
dnl The connectx() function call appeared in Darwin 15.0.0
dnl but it's not declared using availability attribute.
dnl Additionally _connectx symbol is part of OS X 10.9/10.10
dnl system lib but does not have specified functionality.
dnl

AC_DEFUN([CURL_CHECK_FUNC_CONNECTX], [
AC_REQUIRE([CURL_MAC_CFLAGS])dnl
AC_CHECK_FUNCS([connectx])
AC_MSG_CHECKING([if connectx is available in deployment target])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[
#if defined(HAVE_CONNECTX)
# include <Availability.h>
# if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
# if (__MAC_OS_X_VERSION_MIN_REQUIRED < 101100)
# error Function requires deployment target OS X 10.11 or later
# endif
# elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
# if (__IPHONE_OS_VERSION_MIN_REQUIRED < 90000)
# error Function requires deployment target iOS 9.0 or later
# endif
# endif
#else
# error Function not present in the headers
#endif
]])],
[
AC_DEFINE(HAVE_VALID_CONNECTX, 1,
[Set to 1 if connectx() function have specified functionality.])
AC_MSG_RESULT([yes])
],
[AC_MSG_RESULT([no])]
)
])
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -3328,6 +3328,7 @@ CURL_CHECK_FUNC_BASENAME
CURL_CHECK_FUNC_CLOSESOCKET
CURL_CHECK_FUNC_CLOSESOCKET_CAMEL
CURL_CHECK_FUNC_CONNECT
CURL_CHECK_FUNC_CONNECTX
CURL_CHECK_FUNC_FCNTL
CURL_CHECK_FUNC_FDOPEN
CURL_CHECK_FUNC_FREEADDRINFO
Expand Down
31 changes: 11 additions & 20 deletions lib/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -1058,26 +1058,17 @@ static CURLcode singleipconnect(struct connectdata *conn,
/* Connect TCP sockets, bind UDP */
if(!isconnected && (conn->socktype == SOCK_STREAM)) {
if(conn->bits.tcp_fastopen) {
#if defined(CONNECT_DATA_IDEMPOTENT) /* OS X */
#ifdef HAVE_BUILTIN_AVAILABLE
if(__builtin_available(macOS 10.11, iOS 9.0, tvOS 9.0, watchOS 2.0, *)) {
#endif /* HAVE_BUILTIN_AVAILABLE */
sa_endpoints_t endpoints;
endpoints.sae_srcif = 0;
endpoints.sae_srcaddr = NULL;
endpoints.sae_srcaddrlen = 0;
endpoints.sae_dstaddr = &addr.sa_addr;
endpoints.sae_dstaddrlen = addr.addrlen;

rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
NULL, 0, NULL, NULL);
#ifdef HAVE_BUILTIN_AVAILABLE
}
else {
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
}
#endif /* HAVE_BUILTIN_AVAILABLE */
#if defined(HAVE_VALID_CONNECTX) /* Darwin */
sa_endpoints_t endpoints;
endpoints.sae_srcif = 0;
endpoints.sae_srcaddr = NULL;
endpoints.sae_srcaddrlen = 0;
endpoints.sae_dstaddr = &addr.sa_addr;
endpoints.sae_dstaddrlen = addr.addrlen;

rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
NULL, 0, NULL, NULL);
#elif defined(MSG_FASTOPEN) /* Linux */
if(conn->given->flags & PROTOPT_SSL)
rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
Expand Down
6 changes: 6 additions & 0 deletions lib/curl_config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@
/* Define to 1 if bool is an available type. */
#cmakedefine HAVE_BOOL_T 1

/* Define to 1 if you have the connectx function. */
#cmakedefine HAVE_CONNECTX 1

/* Define to 1 if you have the clock_gettime function and monotonic timer. */
#cmakedefine HAVE_CLOCK_GETTIME_MONOTONIC 1

Expand Down Expand Up @@ -716,6 +719,9 @@
/* Define to 1 if you have the <utime.h> header file. */
#cmakedefine HAVE_UTIME_H 1

/* Define to 1 if you have valid connectx function. */
#cmakedefine HAVE_VALID_CONNECTX 1

/* Define to 1 if compiler supports C99 variadic macro style. */
#cmakedefine HAVE_VARIADIC_MACROS_C99 1

Expand Down
2 changes: 1 addition & 1 deletion lib/url.c
Original file line number Diff line number Diff line change
Expand Up @@ -2900,7 +2900,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
data->set.tcp_keepintvl = va_arg(param, long);
break;
case CURLOPT_TCP_FASTOPEN:
#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN)
#if defined(HAVE_VALID_CONNECTX) || defined(MSG_FASTOPEN)
data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
#else
result = CURLE_NOT_BUILT_IN;
Expand Down

0 comments on commit f28aac9

Please sign in to comment.