summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph M. Becker <cmbecker69@gmx.de>2020-03-11 10:16:04 +0100
committerChristoph M. Becker <cmbecker69@gmx.de>2020-03-11 11:30:15 +0100
commit53797c206a4304e0c322c39cb02abf891429367e (patch)
tree4609957fb50b81d618aa6ca33c4e62db394e8eb2
parent2462f2dab185f53544f2c5335ba6c16a007f3c71 (diff)
downloadphp-git-53797c206a4304e0c322c39cb02abf891429367e.tar.gz
Fix #78210: Invalid pointer address
This is actually about three distinct issues: * If an empty string is passed as $address to `stream_socket_sendto()`, the `sa` is not initialized, so we must not pass it as `addr` to `php_stream_xport_sendto()`. * On POSIX, `recvfrom()` truncates messages which are too long to fit into the specified buffer (unless `MSG_PEEK` is given), discards the excessive bytes, and returns the buffer length. On Windows, the same happens, but `recvfrom()` returns `SOCKET_ERROR` with the error code `WSAEMSGSIZE`. We have to catch this for best POSIX compatibility. * In `php_network_parse_network_address_with_port()`, we have to zero `in6` (not only its alias `sa`) to properly support IPv6. Co-Authored-By: Nikita Popov <nikita.ppv@googlemail.com>
-rw-r--r--NEWS1
-rw-r--r--ext/standard/streamsfuncs.c2
-rw-r--r--main/network.c6
-rw-r--r--main/streams/xp_socket.c6
4 files changed, 12 insertions, 3 deletions
diff --git a/NEWS b/NEWS
index b290b23f81..7d61149ac0 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ PHP NEWS
- Core:
. Fixed bug #79364 (When copy empty array, next key is unspecified). (cmb)
+ . Fixed bug #78210 (Invalid pointer address). (cmb, Nikita)
- Spl:
. Fixed bug #75673 (SplStack::unserialize() behavior). (cmb)
diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c
index 8f0bd8bc8e..6fbfb0bcdc 100644
--- a/ext/standard/streamsfuncs.c
+++ b/ext/standard/streamsfuncs.c
@@ -366,7 +366,7 @@ PHP_FUNCTION(stream_socket_sendto)
}
}
- RETURN_LONG(php_stream_xport_sendto(stream, data, datalen, (int)flags, target_addr ? &sa : NULL, sl));
+ RETURN_LONG(php_stream_xport_sendto(stream, data, datalen, (int)flags, target_addr_len ? &sa : NULL, sl));
}
/* }}} */
diff --git a/main/network.c b/main/network.c
index 21f17e8ade..f00c775c6f 100644
--- a/main/network.c
+++ b/main/network.c
@@ -512,9 +512,11 @@ PHPAPI int php_network_parse_network_address_with_port(const char *addr, zend_lo
zend_string *errstr = NULL;
#if HAVE_IPV6
struct sockaddr_in6 *in6 = (struct sockaddr_in6*)sa;
-#endif
- memset(sa, 0, sizeof(struct sockaddr));
+ memset(in6, 0, sizeof(struct sockaddr_in6));
+#else
+ memset(in4, 0, sizeof(struct sockaddr_in));
+#endif
if (*addr == '[') {
colon = memchr(addr + 1, ']', addrlen-1);
diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c
index acdb1f8876..0ae0c0f77b 100644
--- a/main/streams/xp_socket.c
+++ b/main/streams/xp_socket.c
@@ -272,6 +272,12 @@ static inline int sock_recvfrom(php_netstream_data_t *sock, char *buf, size_t bu
socklen_t sl = sizeof(sa);
ret = recvfrom(sock->socket, buf, XP_SOCK_BUF_SIZE(buflen), flags, (struct sockaddr*)&sa, &sl);
ret = (ret == SOCK_CONN_ERR) ? -1 : ret;
+#ifdef PHP_WIN32
+ /* POSIX discards excess bytes without signalling failure; emulate this on Windows */
+ if (ret == -1 && WSAGetLastError() == WSAEMSGSIZE) {
+ ret = buflen;
+ }
+#endif
if (sl) {
php_network_populate_name_from_sockaddr((struct sockaddr*)&sa, sl,
textaddr, addr, addrlen);