diff options
author | Joe Watkins <krakjoe@php.net> | 2016-03-31 12:39:01 +0100 |
---|---|---|
committer | Joe Watkins <krakjoe@php.net> | 2016-03-31 12:39:01 +0100 |
commit | 233115ea236fd1aa258e8b733d3855d1261fba8b (patch) | |
tree | db5f522d2d1787169e25b8f2cc4b485e0c67f72e /main/network.c | |
parent | ed06d130f70691cb50bed9dc7b9db38970a9d408 (diff) | |
download | php-git-233115ea236fd1aa258e8b733d3855d1261fba8b.tar.gz |
fix #71609: Segmentation fault on ZTS with gethostbyname
Diffstat (limited to 'main/network.c')
-rw-r--r-- | main/network.c | 94 |
1 files changed, 92 insertions, 2 deletions
diff --git a/main/network.c b/main/network.c index 138f86b3e4..6d1d97bc82 100644 --- a/main/network.c +++ b/main/network.c @@ -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: |