Commits

Ruslan Osmanov committed a1d2b59

Add: EventUtil::getSocketName method
Fix: possible memory access violation in EventBufferEvent methods when bevent ptr is not initialized

Comments (0)

Files changed (7)

 #include "src/priv.h"
 
 /* {{{ _get_pos */
-static zend_always_inline int _get_pos(struct evbuffer_ptr *out_ptr, const long pos, struct evbuffer *buf TSRMLS_CC)
+static int _get_pos(struct evbuffer_ptr *out_ptr, const long pos, struct evbuffer *buf TSRMLS_CC)
 {
 	if (pos < 0) {
 		return FAILURE;

classes/buffer_event.c

 	}
 
 	PHP_EVENT_FETCH_BEVENT(bev, zbevent);
+	_ret_if_invalid_bevent_ptr(bev);
 
 	if (sync_resolve) {
 		/* The PHP API *syncronously* resolves hostname, if it doesn't look
 	}
 
 	PHP_EVENT_FETCH_BEVENT(bev, zbevent);
+	_ret_if_invalid_bevent_ptr(bev);
 
 	/* bufferevent_socket_connect() allocates a socket stream internally, if we
 	 * didn't provide the file descriptor to the bufferevent before, e.g. with
 	}
 
 	PHP_EVENT_FETCH_BEVENT(bev, zbevent);
+	_ret_if_invalid_bevent_ptr(bev);
 
 	err = bufferevent_socket_get_dns_error(bev->bevent);
 
 	}
 
 	PHP_EVENT_FETCH_BEVENT(bev, zbevent);
+	_ret_if_invalid_bevent_ptr(bev);
 
 	if (ZEND_FCI_INITIALIZED(fci_read)) {
 		read_cb = bevent_read_cb;
 	}
 
 	PHP_EVENT_FETCH_BEVENT(bev, zbevent);
+	_ret_if_invalid_bevent_ptr(bev);
+
 
 	RETVAL_LONG(bufferevent_get_enabled(bev->bevent));
 }
 	}
 
 	PHP_EVENT_FETCH_BEVENT(bev, zbevent);
+	_ret_if_invalid_bevent_ptr(bev);
 
 	PHP_EVENT_INIT_CLASS_OBJECT(return_value, php_event_buffer_ce);
 	PHP_EVENT_FETCH_BUFFER(b, return_value);
 	}
 
 	PHP_EVENT_FETCH_BEVENT(bev, zbevent);
-
 	_ret_if_invalid_bevent_ptr(bev);
 
 	bufferevent_setwatermark(bev->bevent, events, (size_t) lowmark, (size_t) highmark);
 	}
 
 	PHP_EVENT_FETCH_BEVENT(bev, zbevent);
-
 	_ret_if_invalid_bevent_ptr(bev);
 
 	convert_to_string(zdata);
 /* }}} */
 #endif/* }}} */
 
+/* {{{ proto bool EventUtil::getSocketName(mixed socket, string &address[, int &port]);
+ * Retreives the current address to which the <parameter>socket</parameter> is bound.
+ *
+ * <parameter>socket</parameter> may be a stream or socket resource, or a numeric file descriptor
+ * associated with a socket.
+ *
+ * Returns &true; on success. Otherwise &false;.*/
+PHP_METHOD(EventUtil, getSocketName)
+{
+	zval            **ppzfd;
+	zval             *zaddress;
+	zval             *zport    = NULL;
+	evutil_socket_t   fd;
+
+	php_sockaddr_storage  sa_storage;
+	struct sockaddr      *sa         = (struct sockaddr *) &sa_storage;
+	socklen_t             sa_len     = sizeof(php_sockaddr_storage);
+	long                  port       = -1;
+
+	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zz|z",
+				&ppzfd, &zaddress, &zport) == FAILURE) {
+		return;
+	}
+
+	fd = (evutil_socket_t) php_event_zval_to_fd(ppzfd TSRMLS_CC);
+	if (fd < 0) {
+		RETURN_FALSE;
+	}
+
+	if (getsockname(fd, sa, &sa_len)) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING,
+				"Unable to retreive socket name, errno: %d", errno);
+		RETURN_FALSE;
+	}
+
+	switch (sa->sa_family) {
+		case AF_INET:
+			{
+				struct sockaddr_in *sin = (struct sockaddr_in *) sa;
+				char addr[INET_ADDRSTRLEN + 1];
+
+				if (evutil_inet_ntop(sa->sa_family, &sin->sin_addr,
+							(void *) &addr, sizeof(addr))) {
+					zval_dtor(zaddress);
+					ZVAL_STRING(zaddress, addr, 1);
+
+					if (zport != NULL) {
+						port = ntohs(sin->sin_port);
+					}
+				}
+			}
+			break;
+#if HAVE_IPV6 && HAVE_INET_NTOP
+		case AF_INET6:
+			{
+				struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+				char addr6[INET6_ADDRSTRLEN + 1];
+
+				if (evutil_inet_ntop(sa->sa_family, &sin6->sin6_addr,
+							(void *) &addr6, sizeof(addr6))) {
+					zval_dtor(zaddress);
+					ZVAL_STRING(zaddress, addr6, 1);
+
+					if (zport != NULL) {
+						port = ntohs(sin6->sin6_port);
+					}
+				}
+			}
+			break;
+#endif
+#ifdef AF_UNIX
+		case AF_UNIX:
+			{
+				struct sockaddr_un *ua = (struct sockaddr_un *) sa;
+
+				zval_dtor(zaddress);
+				ZVAL_STRING(zaddress, ua->sun_path, 1);
+			}
+			break;
+#endif
+		default:
+			php_error_docref(NULL TSRMLS_CC, E_WARNING,
+					"Unsupported address family: %d", sa->sa_family);
+			RETURN_FALSE;
+	}
+
+	if (port != -1) {
+		zval_dtor(zport);
+		ZVAL_LONG(zport, port);
+	}
+
+	RETVAL_TRUE;
+}
+/* }}} */
+
 /*
  * Local variables:
  * tab-width: 4
   Fix: uninitialized socket caused segmentation fault in EventBufferEvent methods
   Del: EventBufferPosition class removed, EventBuffer::search now accepts and returns integers
   Add: EventBuffer::searchEol method
+  Add: EventUtil::getSocketName method
   ]]></notes>
   <!--}}}-->
   <!--{{{ Contents -->
         Fix: uninitialized socket caused segmentation fault in EventBufferEvent methods
         Del: EventBufferPosition class removed, EventBuffer::search now accepts and returns integers
         Add: EventBuffer::searchEol method
+        Add: EventUtil::getSocketName method
         ]]></notes>
     </release>
     <!--}}}-->
 	ZEND_ARG_INFO(0, options)
 ZEND_END_ARG_INFO();
 
+ZEND_BEGIN_ARG_INFO_EX(arginfo_event_util_get_socket_name, 0, 0, 2)
+	ZEND_ARG_INFO(0, socket)
+	ZEND_ARG_INFO(1, address)
+	ZEND_ARG_INFO(1, port)
+ZEND_END_ARG_INFO();
+
+
 /* ARGINFO END }}} */
 
 
 const zend_function_entry php_event_util_ce_functions[] = {/* {{{ */
 	PHP_ABSTRACT_ME(EventUtil, __construct, NULL)
 
-	PHP_ME(EventUtil, getLastSocketErrno, arginfo_event_socket_1, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
-	PHP_ME(EventUtil, getLastSocketError, arginfo_event_socket_1, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+	PHP_ME(EventUtil, getLastSocketErrno,    arginfo_event_socket_1,             ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+	PHP_ME(EventUtil, getLastSocketError,    arginfo_event_socket_1,             ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
 
-#ifdef HAVE_EVENT_OPENSSL_LIB
-	PHP_ME(EventUtil, sslRandPoll,        arginfo_event__void,    ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
+#ifdef            HAVE_EVENT_OPENSSL_LIB
+	PHP_ME(EventUtil, sslRandPoll,           arginfo_event__void,                ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
 #endif
+	PHP_ME(EventUtil, getSocketName,         arginfo_event_util_get_socket_name, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
 
 	PHP_FE_END
 };
 #ifdef HAVE_EVENT_OPENSSL_LIB
 PHP_METHOD(EventUtil, sslRandPoll);
 #endif
+PHP_METHOD(EventUtil, getSocketName);
 
 PHP_METHOD(EventBufferPosition, __construct);
 
 }
 /* }}} */
 
-
 /*
  * Local variables:
  * tab-width: 4