summaryrefslogtreecommitdiff
path: root/main/network.c
diff options
context:
space:
mode:
authorJoe Watkins <krakjoe@php.net>2016-03-31 12:39:01 +0100
committerJoe Watkins <krakjoe@php.net>2016-03-31 12:39:01 +0100
commit233115ea236fd1aa258e8b733d3855d1261fba8b (patch)
treedb5f522d2d1787169e25b8f2cc4b485e0c67f72e /main/network.c
parented06d130f70691cb50bed9dc7b9db38970a9d408 (diff)
downloadphp-git-233115ea236fd1aa258e8b733d3855d1261fba8b.tar.gz
fix #71609: Segmentation fault on ZTS with gethostbyname
Diffstat (limited to 'main/network.c')
-rw-r--r--main/network.c94
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: