mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
fix #71609: Segmentation fault on ZTS with gethostbyname
This commit is contained in:
parent
ed06d130f7
commit
233115ea23
10 changed files with 315 additions and 10 deletions
197
TSRM/m4/gethostbyname.m4
Normal file
197
TSRM/m4/gethostbyname.m4
Normal file
|
@ -0,0 +1,197 @@
|
|||
# =================================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_func_which_gethostbyname_r.html
|
||||
# =================================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_FUNC_WHICH_GETHOSTBYNAME_R
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Determines which historical variant of the gethostbyname_r() call
|
||||
# (taking three, five, or six arguments) is available on the system and
|
||||
# defines one of the following macros accordingly:
|
||||
#
|
||||
# HAVE_FUNC_GETHOSTBYNAME_R_6
|
||||
# HAVE_FUNC_GETHOSTBYNAME_R_5
|
||||
# HAVE_FUNC_GETHOSTBYNAME_R_3
|
||||
#
|
||||
# as well as
|
||||
#
|
||||
# HAVE_GETHOSTBYNAME_R
|
||||
#
|
||||
# If used in conjunction with gethostname.c, the API demonstrated in
|
||||
# test.c can be used regardless of which gethostbyname_r() is available.
|
||||
# These example files can be found at
|
||||
# http://www.csn.ul.ie/~caolan/publink/gethostbyname_r
|
||||
#
|
||||
# based on David Arnold's autoconf suggestion in the threads faq
|
||||
#
|
||||
# Originally named "AC_caolan_FUNC_WHICH_GETHOSTBYNAME_R". Rewritten for
|
||||
# Autoconf 2.5x, and updated for 2.68 by Daniel Richard G.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Caolan McNamara <caolan@skynet.ie>
|
||||
# Copyright (c) 2008 Daniel Richard G. <skunk@iskunk.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation; either version 2 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 7
|
||||
|
||||
AC_DEFUN([AX_FUNC_WHICH_GETHOSTBYNAME_R], [
|
||||
|
||||
AC_LANG_PUSH([C])
|
||||
AC_MSG_CHECKING([how many arguments gethostbyname_r() takes])
|
||||
|
||||
AC_CACHE_VAL([ac_cv_func_which_gethostbyname_r], [
|
||||
|
||||
################################################################
|
||||
|
||||
ac_cv_func_which_gethostbyname_r=unknown
|
||||
|
||||
#
|
||||
# ONE ARGUMENT (sanity check)
|
||||
#
|
||||
|
||||
# This should fail, as there is no variant of gethostbyname_r() that takes
|
||||
# a single argument. If it actually compiles, then we can assume that
|
||||
# netdb.h is not declaring the function, and the compiler is thereby
|
||||
# assuming an implicit prototype. In which case, we're out of luck.
|
||||
#
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <netdb.h>],
|
||||
[
|
||||
char *name = "www.gnu.org";
|
||||
(void)gethostbyname_r(name) /* ; */
|
||||
])],
|
||||
[ac_cv_func_which_gethostbyname_r=no])
|
||||
|
||||
#
|
||||
# SIX ARGUMENTS
|
||||
# (e.g. Linux)
|
||||
#
|
||||
|
||||
if test "$ac_cv_func_which_gethostbyname_r" = "unknown"; then
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <netdb.h>],
|
||||
[
|
||||
char *name = "www.gnu.org";
|
||||
struct hostent ret, *retp;
|
||||
char buf@<:@1024@:>@;
|
||||
int buflen = 1024;
|
||||
int my_h_errno;
|
||||
(void)gethostbyname_r(name, &ret, buf, buflen, &retp, &my_h_errno) /* ; */
|
||||
])],
|
||||
[ac_cv_func_which_gethostbyname_r=six])
|
||||
|
||||
fi
|
||||
|
||||
#
|
||||
# FIVE ARGUMENTS
|
||||
# (e.g. Solaris)
|
||||
#
|
||||
|
||||
if test "$ac_cv_func_which_gethostbyname_r" = "unknown"; then
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <netdb.h>],
|
||||
[
|
||||
char *name = "www.gnu.org";
|
||||
struct hostent ret;
|
||||
char buf@<:@1024@:>@;
|
||||
int buflen = 1024;
|
||||
int my_h_errno;
|
||||
(void)gethostbyname_r(name, &ret, buf, buflen, &my_h_errno) /* ; */
|
||||
])],
|
||||
[ac_cv_func_which_gethostbyname_r=five])
|
||||
|
||||
fi
|
||||
|
||||
#
|
||||
# THREE ARGUMENTS
|
||||
# (e.g. AIX, HP-UX, Tru64)
|
||||
#
|
||||
|
||||
if test "$ac_cv_func_which_gethostbyname_r" = "unknown"; then
|
||||
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include <netdb.h>],
|
||||
[
|
||||
char *name = "www.gnu.org";
|
||||
struct hostent ret;
|
||||
struct hostent_data data;
|
||||
(void)gethostbyname_r(name, &ret, &data) /* ; */
|
||||
])],
|
||||
[ac_cv_func_which_gethostbyname_r=three])
|
||||
|
||||
fi
|
||||
|
||||
################################################################
|
||||
|
||||
]) dnl end AC_CACHE_VAL
|
||||
|
||||
case "$ac_cv_func_which_gethostbyname_r" in
|
||||
three|five|six)
|
||||
AC_DEFINE([HAVE_GETHOSTBYNAME_R], [1],
|
||||
[Define to 1 if you have some form of gethostbyname_r().])
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$ac_cv_func_which_gethostbyname_r" in
|
||||
three)
|
||||
AC_MSG_RESULT([three])
|
||||
AC_DEFINE([HAVE_FUNC_GETHOSTBYNAME_R_3], [1],
|
||||
[Define to 1 if you have the three-argument form of gethostbyname_r().])
|
||||
;;
|
||||
|
||||
five)
|
||||
AC_MSG_RESULT([five])
|
||||
AC_DEFINE([HAVE_FUNC_GETHOSTBYNAME_R_5], [1],
|
||||
[Define to 1 if you have the five-argument form of gethostbyname_r().])
|
||||
;;
|
||||
|
||||
six)
|
||||
AC_MSG_RESULT([six])
|
||||
AC_DEFINE([HAVE_FUNC_GETHOSTBYNAME_R_6], [1],
|
||||
[Define to 1 if you have the six-argument form of gethostbyname_r().])
|
||||
;;
|
||||
|
||||
no)
|
||||
AC_MSG_RESULT([cannot find function declaration in netdb.h])
|
||||
;;
|
||||
|
||||
unknown)
|
||||
AC_MSG_RESULT([can't tell])
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_ERROR([internal error])
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_LANG_POP
|
||||
|
||||
]) dnl end AC_DEFUN
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
m4_include([TSRM/m4/gethostbyname.m4])
|
||||
|
||||
dnl TSRM_CHECK_GCC_ARG(ARG, ACTION-IF-FOUND, ACTION-IF-NOT_FOUND)
|
||||
AC_DEFUN([TSRM_CHECK_GCC_ARG],[
|
||||
|
@ -32,6 +33,8 @@ AC_CHECK_HEADERS(stdarg.h)
|
|||
|
||||
AC_CHECK_FUNCS(sigprocmask)
|
||||
|
||||
AX_FUNC_WHICH_GETHOSTBYNAME_R()
|
||||
|
||||
])
|
||||
|
||||
|
||||
|
@ -89,7 +92,6 @@ else
|
|||
fi
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([TSRM_THREADS_CHECKS],[
|
||||
|
||||
dnl For the thread implementations, we always use --with-*
|
||||
|
|
|
@ -90,7 +90,7 @@ int php_set_inet_addr(struct sockaddr_in *sin, char *string, php_socket *php_soc
|
|||
if (inet_aton(string, &tmp)) {
|
||||
sin->sin_addr.s_addr = tmp.s_addr;
|
||||
} else {
|
||||
if (strlen(string) > MAXFQDNLEN || ! (host_entry = gethostbyname(string))) {
|
||||
if (strlen(string) > MAXFQDNLEN || ! (host_entry = php_network_gethostbyname(string))) {
|
||||
/* Note: < -10000 indicates a host lookup error */
|
||||
#ifdef PHP_WIN32
|
||||
PHP_SOCKET_ERROR(php_sock, "Host lookup failed", WSAGetLastError());
|
||||
|
|
|
@ -425,9 +425,9 @@ static int php_open_listen_sock(php_socket **php_sock, int port, int backlog) /*
|
|||
*php_sock = sock;
|
||||
|
||||
#ifndef PHP_WIN32
|
||||
if ((hp = gethostbyname("0.0.0.0")) == NULL) {
|
||||
if ((hp = php_network_gethostbyname("0.0.0.0")) == NULL) {
|
||||
#else
|
||||
if ((hp = gethostbyname("localhost")) == NULL) {
|
||||
if ((hp = php_network_gethostbyname("localhost")) == NULL) {
|
||||
#endif
|
||||
efree(sock);
|
||||
return 0;
|
||||
|
|
|
@ -251,7 +251,7 @@ PHP_FUNCTION(gethostbynamel)
|
|||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
hp = gethostbyname(hostname);
|
||||
hp = php_network_gethostbyname(hostname);
|
||||
if (hp == NULL || hp->h_addr_list == NULL) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ static zend_string *php_gethostbyname(char *name)
|
|||
struct in_addr in;
|
||||
char *address;
|
||||
|
||||
hp = gethostbyname(name);
|
||||
hp = php_network_gethostbyname(name);
|
||||
|
||||
if (!hp || !*(hp->h_addr_list)) {
|
||||
return zend_string_init(name, strlen(name), 0);
|
||||
|
|
|
@ -159,6 +159,11 @@ static void file_globals_ctor(php_file_globals *file_globals_p)
|
|||
|
||||
static void file_globals_dtor(php_file_globals *file_globals_p)
|
||||
{
|
||||
#if defined(HAVE_GETHOSTBYNAME_R)
|
||||
if (file_globals_p->tmp_host_buf) {
|
||||
free(file_globals_p->tmp_host_buf);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
PHP_INI_BEGIN()
|
||||
|
|
|
@ -129,6 +129,11 @@ typedef struct {
|
|||
HashTable *stream_filters; /* per-request copy of stream_filters_hash */
|
||||
HashTable *wrapper_errors; /* key: wrapper address; value: linked list of char* */
|
||||
int pclose_wait;
|
||||
#if defined(HAVE_GETHOSTBYNAME_R)
|
||||
struct hostent tmp_host_info;
|
||||
char *tmp_host_buf;
|
||||
size_t tmp_host_buf_len;
|
||||
#endif
|
||||
} php_file_globals;
|
||||
|
||||
#ifdef ZTS
|
||||
|
|
|
@ -692,7 +692,7 @@ int fcgi_listen(const char *path, int backlog)
|
|||
if(strlen(host) > MAXFQDNLEN) {
|
||||
hep = NULL;
|
||||
} else {
|
||||
hep = gethostbyname(host);
|
||||
hep = php_network_gethostbyname(host);
|
||||
}
|
||||
if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) {
|
||||
fcgi_log(FCGI_ERROR, "Cannot resolve host name '%s'!\n", host);
|
||||
|
|
|
@ -176,6 +176,8 @@ PHPAPI int php_network_getaddresses(const char *host, int socktype, struct socka
|
|||
# endif
|
||||
struct addrinfo hints, *res, *sai;
|
||||
#else
|
||||
char *tmp_host_buf = NULL;
|
||||
struct hostent tmp_host_info;
|
||||
struct hostent *host_info;
|
||||
struct in_addr in;
|
||||
#endif
|
||||
|
@ -245,12 +247,11 @@ PHPAPI int php_network_getaddresses(const char *host, int socktype, struct socka
|
|||
freeaddrinfo(res);
|
||||
#else
|
||||
if (!inet_aton(host, &in)) {
|
||||
/* XXX NOT THREAD SAFE (is safe under win32) */
|
||||
if(strlen(host) > MAXFQDNLEN) {
|
||||
host_info = NULL;
|
||||
errno = E2BIG;
|
||||
} else {
|
||||
host_info = gethostbyname(host);
|
||||
host_info = php_network_gethostbyname(host, &tmp_host_info, &tmp_host_buf);
|
||||
}
|
||||
if (host_info == NULL) {
|
||||
if (error_string) {
|
||||
|
@ -271,6 +272,9 @@ PHPAPI int php_network_getaddresses(const char *host, int socktype, struct socka
|
|||
((struct sockaddr_in *)*sap)->sin_addr = in;
|
||||
sap++;
|
||||
n = 1;
|
||||
if (tmp_host_buf) {
|
||||
efree(tmp_host_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
*sap = NULL;
|
||||
|
@ -1257,9 +1261,95 @@ PHPAPI int php_poll2(php_pollfd *ufds, unsigned int nfds, int timeout)
|
|||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_GETHOSTBYNAME_R)
|
||||
#ifdef HAVE_FUNC_GETHOSTBYNAME_R_6
|
||||
struct hostent * gethostname_re (const char *host,struct hostent *hostbuf,char **tmphstbuf,size_t *hstbuflen)
|
||||
{
|
||||
struct hostent *hp;
|
||||
int herr,res;
|
||||
|
||||
if (*hstbuflen == 0) {
|
||||
*hstbuflen = 1024;
|
||||
*tmphstbuf = (char *)malloc (*hstbuflen);
|
||||
}
|
||||
|
||||
while (( res =
|
||||
gethostbyname_r(host,hostbuf,*tmphstbuf,*hstbuflen,&hp,&herr))
|
||||
&& (errno == ERANGE)) {
|
||||
/* Enlarge the buffer. */
|
||||
*hstbuflen *= 2;
|
||||
*tmphstbuf = (char *)realloc (*tmphstbuf,*hstbuflen);
|
||||
}
|
||||
|
||||
if (res != SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hp;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_FUNC_GETHOSTBYNAME_R_5
|
||||
struct hostent * gethostname_re (const char *host,struct hostent *hostbuf,char **tmphstbuf,size_t *hstbuflen)
|
||||
{
|
||||
struct hostent *hp;
|
||||
int herr;
|
||||
|
||||
if (*hstbuflen == 0) {
|
||||
*hstbuflen = 1024;
|
||||
*tmphstbuf = (char *)malloc (*hstbuflen);
|
||||
}
|
||||
|
||||
while ((NULL == ( hp =
|
||||
gethostbyname_r(host,hostbuf,*tmphstbuf,*hstbuflen,&herr)))
|
||||
&& (errno == ERANGE)) {
|
||||
/* Enlarge the buffer. */
|
||||
*hstbuflen *= 2;
|
||||
*tmphstbuf = (char *)realloc (*tmphstbuf,*hstbuflen);
|
||||
}
|
||||
return hp;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_FUNC_GETHOSTBYNAME_R_3
|
||||
struct hostent * gethostname_re (const char *host,struct hostent *hostbuf,char **tmphstbuf,size_t *hstbuflen)
|
||||
{
|
||||
if (*hstbuflen == 0) {
|
||||
*hstbuflen = sizeof(struct hostent_data);
|
||||
*tmphstbuf = (char *)malloc (*hstbuflen);
|
||||
} else {
|
||||
if (*hstbuflen < sizeof(struct hostent_data)) {
|
||||
*hstbuflen = sizeof(struct hostent_data);
|
||||
*tmphstbuf = (char *)realloc(*tmphstbuf, *hstbuflen);
|
||||
}
|
||||
}
|
||||
memset((void *)(*tmphstbuf),0,*hstbuflen);
|
||||
|
||||
if (SUCCESS != gethostbyname_r(host,hostbuf,(struct hostent_data *)*tmphstbuf)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hostbuf;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
PHPAPI struct hostent* php_network_gethostbyname(char *name) {
|
||||
#if !defined(HAVE_GETHOSTBYNAME_R)
|
||||
return gethostbyname(name);
|
||||
#else
|
||||
if (FG(tmp_host_buf)) {
|
||||
free(FG(tmp_host_buf));
|
||||
}
|
||||
|
||||
FG(tmp_host_buf) = NULL;
|
||||
FG(tmp_host_buf_len) = 0;
|
||||
|
||||
memset(&FG(tmp_host_info), 0, sizeof(struct hostent));
|
||||
|
||||
return gethostname_re(name, &FG(tmp_host_info), &FG(tmp_host_buf), &FG(tmp_host_buf_len));
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
|
|
|
@ -74,6 +74,10 @@ END_EXTERN_C()
|
|||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GETHOSTBYNAME_R
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
/* These are here, rather than with the win32 counterparts above,
|
||||
* since <sys/socket.h> defines them. */
|
||||
#ifndef SHUT_RD
|
||||
|
@ -309,6 +313,8 @@ PHPAPI void php_network_populate_name_from_sockaddr(
|
|||
|
||||
PHPAPI int php_network_parse_network_address_with_port(const char *addr,
|
||||
zend_long addrlen, struct sockaddr *sa, socklen_t *sl);
|
||||
|
||||
PHPAPI struct hostent* php_network_gethostbyname(char *name);
|
||||
END_EXTERN_C()
|
||||
|
||||
#define php_stream_sock_open_from_socket(socket, persistent) _php_stream_sock_open_from_socket((socket), (persistent) STREAMS_CC)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue