From 27381069b182d9a7d0a467c054cb8d9cae0ed2df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Mon, 27 Jul 2020 21:23:27 +0200 Subject: [PATCH 1/8] Convert resources to objects in ext/sockets --- UPGRADING | 11 +- ext/sockets/conversions.c | 28 +- ext/sockets/php_sockets.h | 22 +- ext/sockets/sendrecvmsg.c | 15 +- ext/sockets/sockets.c | 593 +++++++++--------- ext/sockets/sockets.stub.php | 147 ++--- ext/sockets/sockets_arginfo.h | 84 +-- ext/sockets/tests/bug76839.phpt | 4 +- ext/sockets/tests/ipv4loop.phpt | 6 + ext/sockets/tests/ipv6loop.phpt | 6 + ext/sockets/tests/mcast_ipv4_recv.phpt | 3 +- ext/sockets/tests/mcast_ipv6_recv.phpt | 6 +- .../tests/mcast_ipv6_recv_limited.phpt | 6 +- ext/sockets/tests/socket_addrinfo_bind.phpt | 5 +- .../tests/socket_addrinfo_connect.phpt | 5 +- ext/sockets/tests/socket_addrinfo_lookup.phpt | 3 +- .../tests/socket_cmsg_credentials.phpt | 8 +- ext/sockets/tests/socket_cmsg_rights.phpt | 8 +- .../tests/socket_create_listen_used.phpt | 3 +- ext/sockets/tests/socket_create_pair.phpt | 6 +- ext/sockets/tests/socket_export_stream-2.phpt | 3 +- ext/sockets/tests/socket_export_stream-3.phpt | 3 +- ext/sockets/tests/socket_import_stream-1.phpt | 3 +- ext/sockets/tests/socket_import_stream-3.phpt | 6 +- ext/sockets/tests/socket_recvmsg.phpt | 6 +- .../socket_sendrecvmsg_multi_msg-unix.phpt | 6 +- .../tests/socket_sendrecvmsg_multi_msg.phpt | 6 +- ext/sockets/tests/socket_set_nonblock.phpt | 5 +- ext/sockets/tests/wsaprotocol_info_0.phpt | 9 +- 29 files changed, 527 insertions(+), 489 deletions(-) diff --git a/UPGRADING b/UPGRADING index d4ddcede72fa2..f1b34a53877e1 100644 --- a/UPGRADING +++ b/UPGRADING @@ -459,9 +459,18 @@ PHP 8.0 UPGRADE NOTES . ReflectionType::isBuiltin() method has been moved to ReflectionNamedType. ReflectionUnionType does not have it. -- Socket: +- Sockets: . The deprecated AI_IDN_ALLOW_UNASSIGNED and AI_IDN_USE_STD3_ASCII_RULES flags for socket_addrinfo_lookup() have been removed. + . socket_create(), socket_create_listen(), socket_accept(), + socket_import_stream(), socket_addrinfo_connect(), socket_addrinfo_bind(), + and socket_wsaprotocol_info_import() will now return a Socket object rather + than a resource. Return value checks using is_resource() should be replaced + with checks for `false`. The socket_close() function is deprecated and no + longer has an effect, instead the Socket instance is automatically + destroyed if it is no longer referenced. + . socket_addrinfo_lookup() will now return an array of AddressInfo objects + rather than resources. - SPL: . SplFileObject::fgetss() has been removed. diff --git a/ext/sockets/conversions.c b/ext/sockets/conversions.c index f2c66758cbfa5..712c1cef53c2f 100644 --- a/ext/sockets/conversions.c +++ b/ext/sockets/conversions.c @@ -1339,29 +1339,26 @@ static void from_zval_write_fd_array_aux(zval *elem, unsigned i, void **args, se { int *iarr = args[0]; - if (Z_TYPE_P(elem) == IS_RESOURCE) { - php_stream *stream; - php_socket *sock; + if (Z_TYPE_P(elem) == IS_OBJECT && Z_OBJCE_P(elem) == socket_ce) { + php_socket *sock = Z_SOCKET_P(elem); + iarr[i] = sock->bsd_socket; - sock = (php_socket *)zend_fetch_resource_ex(elem, NULL, php_sockets_le_socket()); - if (sock) { - iarr[i] = sock->bsd_socket; - return; - } + return; + } else if (Z_TYPE_P(elem) == IS_RESOURCE) { + php_stream *stream; stream = (php_stream *)zend_fetch_resource2_ex(elem, NULL, php_file_le_stream(), php_file_le_pstream()); if (stream == NULL) { - do_from_zval_err(ctx, "resource is not a stream or a socket"); + do_from_zval_err(ctx, "resource is not a stream"); return; } - if (php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&iarr[i - 1], - REPORT_ERRORS) == FAILURE) { + if (php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&iarr[i - 1], REPORT_ERRORS) == FAILURE) { do_from_zval_err(ctx, "cast stream to file descriptor failed"); return; } } else { - do_from_zval_err(ctx, "expected a resource variable"); + do_from_zval_err(ctx, "expected a Socket object or a stream resource"); } } void from_zval_write_fd_array(const zval *arr, char *int_arr, ser_context *ctx) @@ -1412,8 +1409,11 @@ void to_zval_read_fd_array(const char *data, zval *zv, res_context *ctx) return; } if (S_ISSOCK(statbuf.st_mode)) { - php_socket *sock = socket_import_file_descriptor(fd); - ZVAL_RES(&elem, zend_register_resource(sock, php_sockets_le_socket())); + + object_init_ex(&elem, socket_ce); + php_socket *sock = Z_SOCKET_P(&elem); + + socket_import_file_descriptor(fd, sock); } else { php_stream *stream = php_stream_fopen_from_fd(fd, "rw", NULL); php_stream_to_zval(stream, &elem); diff --git a/ext/sockets/php_sockets.h b/ext/sockets/php_sockets.h index 7f67040ce3c72..d8008b07cfa88 100644 --- a/ext/sockets/php_sockets.h +++ b/ext/sockets/php_sockets.h @@ -52,14 +52,26 @@ typedef int PHP_SOCKET; typedef SOCKET PHP_SOCKET; #endif +/* Socket class */ + typedef struct { PHP_SOCKET bsd_socket; int type; int error; int blocking; zval zstream; + zend_object std; } php_socket; +zend_class_entry *socket_ce; + +static inline php_socket *socket_from_obj(zend_object *obj) { + return (php_socket *)((char *)(obj) - XtOffsetOf(php_socket, std)); +} + +#define Z_SOCKET_P(zv) socket_from_obj(Z_OBJ_P(zv)) + + #ifdef PHP_WIN32 struct sockaddr_un { short sun_family; @@ -67,14 +79,6 @@ struct sockaddr_un { }; #endif -PHP_SOCKETS_API int php_sockets_le_socket(void); -PHP_SOCKETS_API php_socket *php_create_socket(void); -PHP_SOCKETS_API void php_destroy_socket(zend_resource *rsrc); -PHP_SOCKETS_API void php_destroy_sockaddr(zend_resource *rsrc); - -#define php_sockets_le_socket_name "Socket" -#define php_sockets_le_addrinfo_name "AddressInfo" - #define PHP_SOCKET_ERROR(socket, msg, errn) \ do { \ int _err = (errn); /* save value to avoid repeated calls to WSAGetLastError() on Windows */ \ @@ -104,7 +108,7 @@ enum sockopt_return { }; char *sockets_strerror(int error); -php_socket *socket_import_file_descriptor(PHP_SOCKET sock); +int socket_import_file_descriptor(PHP_SOCKET socket, php_socket *retsock); #else #define phpext_sockets_ptr NULL diff --git a/ext/sockets/sendrecvmsg.c b/ext/sockets/sendrecvmsg.c index 32f559a192258..c7194e7798f35 100644 --- a/ext/sockets/sendrecvmsg.c +++ b/ext/sockets/sendrecvmsg.c @@ -172,16 +172,13 @@ PHP_FUNCTION(socket_sendmsg) ssize_t res; /* zmsg should be passed by ref */ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ra|l", &zsocket, &zmsg, &flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oa|l", &zsocket, socket_ce, &zmsg, &flags) == FAILURE) { RETURN_THROWS(); } LONG_CHECK_VALID_INT(flags, 3); - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(zsocket), - php_sockets_le_socket_name, php_sockets_le_socket())) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(zsocket); msghdr = from_zval_run_conversions(zmsg, php_sock, from_zval_write_msghdr_send, sizeof(*msghdr), "msghdr", &allocations, &err); @@ -216,17 +213,13 @@ PHP_FUNCTION(socket_recvmsg) struct err_s err = {0}; //ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ra|l", - &zsocket, &zmsg, &flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oa|l", &zsocket, socket_ce, &zmsg, &flags) == FAILURE) { RETURN_THROWS(); } LONG_CHECK_VALID_INT(flags, 3); - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(zsocket), - php_sockets_le_socket_name, php_sockets_le_socket())) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(zsocket); msghdr = from_zval_run_conversions(zmsg, php_sock, from_zval_write_msghdr_recv, sizeof(*msghdr), "msghdr", &allocations, &err); diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index d17203f0a484b..6b6af26215049 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -28,6 +28,7 @@ #include "ext/standard/file.h" #include "ext/standard/info.h" #include "php_ini.h" +#include "zend_interfaces.h" #ifdef PHP_WIN32 # include "windows_common.h" # include @@ -92,12 +93,6 @@ ZEND_DECLARE_MODULE_GLOBALS(sockets) #define PHP_NORMAL_READ 0x0001 #define PHP_BINARY_READ 0x0002 -static int le_socket; -#define le_socket_name php_sockets_le_socket_name - -static int le_addrinfo; -#define le_addrinfo_name php_sockets_le_addrinfo_name - static PHP_GINIT_FUNCTION(sockets); static PHP_GSHUTDOWN_FUNCTION(sockets); static PHP_MINIT_FUNCTION(sockets); @@ -105,6 +100,103 @@ static PHP_MSHUTDOWN_FUNCTION(sockets); static PHP_MINFO_FUNCTION(sockets); static PHP_RSHUTDOWN_FUNCTION(sockets); +/* Socket class */ + +static zend_object_handlers socket_object_handlers; + +static zend_object *socket_create_object(zend_class_entry *class_type) { + php_socket *intern = zend_object_alloc(sizeof(php_socket), class_type); + + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &socket_object_handlers; + + intern->bsd_socket = -1; /* invalid socket */ + intern->type = PF_UNSPEC; + intern->error = 0; + intern->blocking = 1; + ZVAL_UNDEF(&intern->zstream); + + return &intern->std; +} + +static zend_function *socket_get_constructor(zend_object *object) { + zend_throw_error(NULL, "Cannot directly construct Socket, use socket_create() instead"); + return NULL; +} + +static void socket_free_obj(zend_object *object) +{ + php_socket *socket = socket_from_obj(object); + + if (Z_ISUNDEF(socket->zstream)) { + if (!IS_INVALID_SOCKET(socket)) { + close(socket->bsd_socket); + } + } else { + zval_ptr_dtor(&socket->zstream); + } + + zend_object_std_dtor(&socket->std); +} + +static HashTable *socket_get_gc(zend_object *object, zval **table, int *n) +{ + php_socket *socket = socket_from_obj(object); + + zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); + + zend_get_gc_buffer_add_zval(gc_buffer, &socket->zstream); + zend_get_gc_buffer_use(gc_buffer, table, n); + + return zend_std_get_properties(object); +} + +/* AddressInfo class */ + +typedef struct { + struct addrinfo *addrinfo; + zend_object std; +} php_addrinfo; + +zend_class_entry *address_info_ce; +static zend_object_handlers address_info_object_handlers; + +static inline php_addrinfo *address_info_from_obj(zend_object *obj) { + return (php_addrinfo *)((char *)(obj) - XtOffsetOf(php_addrinfo, std)); +} + +#define Z_ADDRESS_INFO_P(zv) address_info_from_obj(Z_OBJ_P(zv)) + +static zend_object *address_info_create_object(zend_class_entry *class_type) { + php_addrinfo *intern = zend_object_alloc(sizeof(php_addrinfo), class_type); + + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + intern->std.handlers = &address_info_object_handlers; + + return &intern->std; +} + +static zend_function *address_info_get_constructor(zend_object *object) { + zend_throw_error(NULL, "Cannot directly construct AddressInfo, use socket_addrinfo_lookup() instead"); + return NULL; +} + +static void address_info_free_obj(zend_object *object) +{ + php_addrinfo *address_info = address_info_from_obj(object); + + efree(address_info->addrinfo->ai_addr); + if (address_info->addrinfo->ai_canonname != NULL) { + efree(address_info->addrinfo->ai_canonname); + } + + zend_object_std_dtor(&address_info->std); +} + +/* Module registration */ + zend_module_entry sockets_module_entry = { STANDARD_MODULE_HEADER, "sockets", @@ -133,68 +225,16 @@ ZEND_GET_MODULE(sockets) /* inet_ntop should be used instead of inet_ntoa */ int inet_ntoa_lock = 0; -PHP_SOCKETS_API int php_sockets_le_socket(void) /* {{{ */ -{ - return le_socket; -} -/* }}} */ - -/* allocating function to make programming errors due to uninitialized fields - * less likely */ -PHP_SOCKETS_API php_socket *php_create_socket(void) /* {{{ */ -{ - php_socket *php_sock = emalloc(sizeof(php_socket)); - - php_sock->bsd_socket = -1; /* invalid socket */ - php_sock->type = PF_UNSPEC; - php_sock->error = 0; - php_sock->blocking = 1; - ZVAL_UNDEF(&php_sock->zstream); - - return php_sock; -} -/* }}} */ - -PHP_SOCKETS_API void php_destroy_socket(zend_resource *rsrc) /* {{{ */ -{ - php_socket *php_sock = rsrc->ptr; - - if (Z_ISUNDEF(php_sock->zstream)) { - if (!IS_INVALID_SOCKET(php_sock)) { - close(php_sock->bsd_socket); - } - } else { - zval_ptr_dtor(&php_sock->zstream); - } - efree(php_sock); -} -/* }}} */ - -PHP_SOCKETS_API void php_destroy_addrinfo(zend_resource *rsrc) /* {{{ */ -{ - struct addrinfo *addr = rsrc->ptr; - efree(addr->ai_addr); - if (addr->ai_canonname != NULL) { - efree(addr->ai_canonname); - } - efree(addr); -} -/* }}} */ - -static int php_open_listen_sock(php_socket **php_sock, int port, int backlog) /* {{{ */ +static int php_open_listen_sock(php_socket *sock, int port, int backlog) /* {{{ */ { struct sockaddr_in la; struct hostent *hp; - php_socket *sock = php_create_socket(); - - *php_sock = sock; #ifndef PHP_WIN32 if ((hp = php_network_gethostbyname("0.0.0.0")) == NULL) { #else if ((hp = php_network_gethostbyname("localhost")) == NULL) { #endif - efree(sock); return 0; } @@ -207,7 +247,6 @@ static int php_open_listen_sock(php_socket **php_sock, int port, int backlog) /* if (IS_INVALID_SOCKET(sock)) { PHP_SOCKET_ERROR(sock, "unable to create listening socket", errno); - efree(sock); return 0; } @@ -216,14 +255,12 @@ static int php_open_listen_sock(php_socket **php_sock, int port, int backlog) /* if (bind(sock->bsd_socket, (struct sockaddr *)&la, sizeof(la)) != 0) { PHP_SOCKET_ERROR(sock, "unable to bind to given address", errno); close(sock->bsd_socket); - efree(sock); return 0; } if (listen(sock->bsd_socket, backlog) != 0) { PHP_SOCKET_ERROR(sock, "unable to listen on socket", errno); close(sock->bsd_socket); - efree(sock); return 0; } @@ -231,12 +268,8 @@ static int php_open_listen_sock(php_socket **php_sock, int port, int backlog) /* } /* }}} */ -static int php_accept_connect(php_socket *in_sock, php_socket **new_sock, struct sockaddr *la, socklen_t *la_len) /* {{{ */ +static int php_accept_connect(php_socket *in_sock, php_socket *out_sock, struct sockaddr *la, socklen_t *la_len) /* {{{ */ { - php_socket *out_sock = php_create_socket(); - - *new_sock = out_sock; - out_sock->bsd_socket = accept(in_sock->bsd_socket, la, la_len); if (IS_INVALID_SOCKET(out_sock)) { @@ -401,8 +434,35 @@ static PHP_MINIT_FUNCTION(sockets) #if defined(COMPILE_DL_SOCKETS) && defined(ZTS) ZEND_TSRMLS_CACHE_UPDATE(); #endif - le_socket = zend_register_list_destructors_ex(php_destroy_socket, NULL, le_socket_name, module_number); - le_addrinfo = zend_register_list_destructors_ex(php_destroy_addrinfo, NULL, le_addrinfo_name, module_number); + + zend_class_entry ce_socket; + INIT_CLASS_ENTRY(ce_socket, "Socket", class_Socket_methods); + socket_ce = zend_register_internal_class(&ce_socket); + socket_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES; + socket_ce->create_object = socket_create_object; + socket_ce->serialize = zend_class_serialize_deny; + socket_ce->unserialize = zend_class_unserialize_deny; + + memcpy(&socket_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + socket_object_handlers.offset = XtOffsetOf(php_socket, std); + socket_object_handlers.free_obj = socket_free_obj; + socket_object_handlers.get_constructor = socket_get_constructor; + socket_object_handlers.clone_obj = NULL; + socket_object_handlers.get_gc = socket_get_gc; + + zend_class_entry ce_address_info; + INIT_CLASS_ENTRY(ce_address_info, "AddressInfo", class_AddressInfo_methods); + address_info_ce = zend_register_internal_class(&ce_address_info); + address_info_ce->ce_flags |= ZEND_ACC_FINAL | ZEND_ACC_NO_DYNAMIC_PROPERTIES; + address_info_ce->create_object = address_info_create_object; + address_info_ce->serialize = zend_class_serialize_deny; + address_info_ce->unserialize = zend_class_unserialize_deny; + + memcpy(&address_info_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + address_info_object_handlers.offset = XtOffsetOf(php_addrinfo, std); + address_info_object_handlers.free_obj = address_info_free_obj; + address_info_object_handlers.get_constructor = address_info_get_constructor; + address_info_object_handlers.clone_obj = NULL; REGISTER_LONG_CONSTANT("AF_UNIX", AF_UNIX, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("AF_INET", AF_INET, CONST_CS | CONST_PERSISTENT); @@ -583,7 +643,7 @@ static PHP_RSHUTDOWN_FUNCTION(sockets) } /* }}} */ -static int php_sock_array_to_fd_set(zval *sock_array, fd_set *fds, PHP_SOCKET *max_fd) /* {{{ */ +static int php_sock_array_to_fd_set(uint32_t arg_num, zval *sock_array, fd_set *fds, PHP_SOCKET *max_fd) /* {{{ */ { zval *element; php_socket *php_sock; @@ -593,8 +653,13 @@ static int php_sock_array_to_fd_set(zval *sock_array, fd_set *fds, PHP_SOCKET *m ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(sock_array), element) { ZVAL_DEREF(element); - php_sock = (php_socket*) zend_fetch_resource_ex(element, le_socket_name, le_socket); - if (!php_sock) return -1; /* If element is not a resource, bail out */ + + if (Z_TYPE_P(element) != IS_OBJECT || Z_OBJCE_P(element) != socket_ce) { + zend_argument_type_error(arg_num, "must only have elements of type Socket, %s given", zend_zval_type_name(element)); + return -1; + } + + php_sock = Z_SOCKET_P(element); PHP_SAFE_FD_SET(php_sock->bsd_socket, fds); if (php_sock->bsd_socket > *max_fd) { @@ -617,13 +682,14 @@ static int php_sock_array_from_fd_set(zval *sock_array, fd_set *fds) /* {{{ */ zend_ulong num_key; zend_string *key; - if (Z_TYPE_P(sock_array) != IS_ARRAY) return 0; + ZEND_ASSERT(Z_TYPE_P(sock_array) == IS_ARRAY); array_init(&new_hash); ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(sock_array), num_key, key, element) { ZVAL_DEREF(element); - php_sock = (php_socket*) zend_fetch_resource_ex(element, le_socket_name, le_socket); - ZEND_ASSERT(php_sock); /* element is supposed to be resource */ + + php_sock = Z_SOCKET_P(element); + ZEND_ASSERT(php_sock); /* element is supposed to be Socket object */ if (PHP_SAFE_FD_ISSET(php_sock->bsd_socket, fds)) { /* Add fd to new array */ @@ -669,28 +735,27 @@ PHP_FUNCTION(socket_select) FD_ZERO(&efds); if (r_array != NULL) { - sets += retval = php_sock_array_to_fd_set(r_array, &rfds, &max_fd); + sets += retval = php_sock_array_to_fd_set(1, r_array, &rfds, &max_fd); if (retval == -1) { - return; + RETURN_THROWS(); } } if (w_array != NULL) { - sets += retval = php_sock_array_to_fd_set(w_array, &wfds, &max_fd); + sets += retval = php_sock_array_to_fd_set(2, w_array, &wfds, &max_fd); if (retval == -1) { - return; + RETURN_THROWS(); } } if (e_array != NULL) { - sets += retval = php_sock_array_to_fd_set(e_array, &efds, &max_fd); + sets += retval = php_sock_array_to_fd_set(3, e_array, &efds, &max_fd); if (retval == -1) { - return; + RETURN_THROWS(); } } if (!sets) { - /* TODO Convert to Error? */ - php_error_docref(NULL, E_WARNING, "No resource arrays were passed to select"); - RETURN_FALSE; + zend_value_error("socket_select(): At least one array argument must be passed"); + RETURN_THROWS(); } PHP_SAFE_MAX_FD(max_fd, 0); /* someone needs to make this look more like stream_socket_select */ @@ -735,38 +800,40 @@ PHP_FUNCTION(socket_create_listen) RETURN_THROWS(); } - if (!php_open_listen_sock(&php_sock, port, backlog)) { + object_init_ex(return_value, socket_ce); + php_sock = Z_SOCKET_P(return_value); + + if (!php_open_listen_sock(php_sock, port, backlog)) { + zval_ptr_dtor(return_value); RETURN_FALSE; } php_sock->error = 0; php_sock->blocking = 1; - - RETURN_RES(zend_register_resource(php_sock, le_socket)); } /* }}} */ /* {{{ Accepts a connection on the listening socket fd */ PHP_FUNCTION(socket_accept) { - zval *arg1; + zval *arg1; php_socket *php_sock, *new_sock; php_sockaddr_storage sa; socklen_t php_sa_len = sizeof(sa); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg1) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &arg1, socket_ce) == FAILURE) { RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(arg1); - if (!php_accept_connect(php_sock, &new_sock, (struct sockaddr*)&sa, &php_sa_len)) { + object_init_ex(return_value, socket_ce); + new_sock = Z_SOCKET_P(return_value); + + if (!php_accept_connect(php_sock, new_sock, (struct sockaddr*)&sa, &php_sa_len)) { + zval_ptr_dtor(return_value); RETURN_FALSE; } - - RETURN_RES(zend_register_resource(new_sock, le_socket)); } /* }}} */ @@ -776,13 +843,11 @@ PHP_FUNCTION(socket_set_nonblock) zval *arg1; php_socket *php_sock; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg1) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &arg1, socket_ce) == FAILURE) { RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(arg1); if (!Z_ISUNDEF(php_sock->zstream)) { php_stream *stream; @@ -813,13 +878,11 @@ PHP_FUNCTION(socket_set_block) zval *arg1; php_socket *php_sock; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg1) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &arg1, socket_ce) == FAILURE) { RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(arg1); /* if socket was created from a stream, give the stream a chance to take * care of the operation itself, thereby allowing it to update its internal @@ -853,13 +916,11 @@ PHP_FUNCTION(socket_listen) php_socket *php_sock; zend_long backlog = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &arg1, &backlog) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l", &arg1, socket_ce, &backlog) == FAILURE) { RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(arg1); if (listen(php_sock->bsd_socket, backlog) != 0) { PHP_SOCKET_ERROR(php_sock, "unable to listen on socket", errno); @@ -873,28 +934,10 @@ PHP_FUNCTION(socket_listen) PHP_FUNCTION(socket_close) { zval *arg1; - php_socket *php_sock; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg1) == FAILURE) { - RETURN_THROWS(); - } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &arg1, socket_ce) == FAILURE) { RETURN_THROWS(); } - - if (!Z_ISUNDEF(php_sock->zstream)) { - php_stream *stream = NULL; - php_stream_from_zval_no_verify(stream, &php_sock->zstream); - if (stream != NULL) { - /* close & destroy stream, incl. removing it from the rsrc list; - * resource stored in php_sock->zstream will become invalid */ - php_stream_free(stream, - PHP_STREAM_FREE_KEEP_RSRC | PHP_STREAM_FREE_CLOSE | - (stream->is_persistent?PHP_STREAM_FREE_CLOSE_PERSISTENT:0)); - } - } - zend_list_close(Z_RES_P(arg1)); } /* }}} */ @@ -906,22 +949,21 @@ PHP_FUNCTION(socket_write) int retval; size_t str_len; zend_long length = 0; + zend_bool length_is_null = 1; char *str; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|l", &arg1, &str, &str_len, &length) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os|l!", &arg1, socket_ce, &str, &str_len, &length, &length_is_null) == FAILURE) { RETURN_THROWS(); } + php_sock = Z_SOCKET_P(arg1); + if (length < 0) { zend_argument_value_error(3, "must be greater than or equal to 0"); RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } - - if (ZEND_NUM_ARGS() < 3) { + if (length_is_null) { length = str_len; } @@ -949,10 +991,12 @@ PHP_FUNCTION(socket_read) int retval; zend_long length, type = PHP_BINARY_READ; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|l", &arg1, &length, &type) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol|l", &arg1, socket_ce, &length, &type) == FAILURE) { RETURN_THROWS(); } + php_sock = Z_SOCKET_P(arg1); + /* overflow check */ if ((length + 1) < 2) { RETURN_FALSE; @@ -960,10 +1004,6 @@ PHP_FUNCTION(socket_read) tmpbuf = zend_string_alloc(length, 0); - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } - if (type == PHP_NORMAL_READ) { retval = php_read(php_sock, ZSTR_VAL(tmpbuf), length, 0); } else { @@ -1015,13 +1055,11 @@ PHP_FUNCTION(socket_getsockname) char *addr_string; socklen_t salen = sizeof(php_sockaddr_storage); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz|z", &arg1, &addr, &port) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oz|z", &arg1, socket_ce, &addr, &port) == FAILURE) { RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(arg1); sa = (struct sockaddr *) &sa_storage; @@ -1088,13 +1126,11 @@ PHP_FUNCTION(socket_getpeername) char *addr_string; socklen_t salen = sizeof(php_sockaddr_storage); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz|z", &arg1, &arg2, &arg3) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oz|z", &arg1, socket_ce, &arg2, &arg3) == FAILURE) { RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(arg1); sa = (struct sockaddr *) &sa_storage; @@ -1152,10 +1188,9 @@ PHP_FUNCTION(socket_getpeername) PHP_FUNCTION(socket_create) { zend_long domain, type, protocol; - php_socket *php_sock = php_create_socket(); + php_socket *php_sock; if (zend_parse_parameters(ZEND_NUM_ARGS(), "lll", &domain, &type, &protocol) == FAILURE) { - efree(php_sock); RETURN_THROWS(); } @@ -1164,32 +1199,31 @@ PHP_FUNCTION(socket_create) && domain != AF_INET6 #endif && domain != AF_INET) { - zend_argument_value_error(1, "must be either AF_UNIX, AF_INET6 or AF_INET"); - efree(php_sock); + zend_argument_value_error(1, "must be either AF_UNIX, AF_INET6, or AF_INET"); RETURN_THROWS(); } if (type > 10) { zend_argument_value_error(2, "must be either SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET," " SOCK_RAW, or SOCK_RDM"); - efree(php_sock); RETURN_THROWS(); } + object_init_ex(return_value, socket_ce); + php_sock = Z_SOCKET_P(return_value); + php_sock->bsd_socket = socket(domain, type, protocol); php_sock->type = domain; if (IS_INVALID_SOCKET(php_sock)) { SOCKETS_G(last_error) = errno; php_error_docref(NULL, E_WARNING, "Unable to create socket [%d]: %s", errno, sockets_strerror(errno)); - efree(php_sock); + zval_ptr_dtor(return_value); RETURN_FALSE; } php_sock->error = 0; php_sock->blocking = 1; - - RETURN_RES(zend_register_resource(php_sock, le_socket)); } /* }}} */ @@ -1201,22 +1235,21 @@ PHP_FUNCTION(socket_connect) char *addr; int retval; size_t addr_len; - zend_long port = 0; + zend_long port; + zend_bool port_is_null; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|l", &resource_socket, &addr, &addr_len, &port) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os|l!", &resource_socket, socket_ce, &addr, &addr_len, &port, &port_is_null) == FAILURE) { RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(resource_socket), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(resource_socket); switch(php_sock->type) { #if HAVE_IPV6 case AF_INET6: { struct sockaddr_in6 sin6 = {0}; - if (ZEND_NUM_ARGS() != 3) { + if (port) { zend_argument_value_error(3, "must be specified for the AF_INET6 socket type"); RETURN_THROWS(); } @@ -1237,8 +1270,8 @@ PHP_FUNCTION(socket_connect) case AF_INET: { struct sockaddr_in sin = {0}; - if (ZEND_NUM_ARGS() != 3) { - zend_argument_value_error(3, "must be specified for the AF_INET socket type"); + if (port_is_null) { + zend_argument_value_error(3, "cannot be null for the AF_INET socket type"); RETURN_THROWS(); } @@ -1307,13 +1340,11 @@ PHP_FUNCTION(socket_bind) zend_long port = 0; zend_long retval = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|l", &arg1, &addr, &addr_len, &port) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os|l", &arg1, socket_ce, &addr, &addr_len, &port) == FAILURE) { RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(arg1); switch(php_sock->type) { case AF_UNIX: @@ -1386,13 +1417,11 @@ PHP_FUNCTION(socket_recv) int retval; zend_long len, flags; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rzll", &php_sock_res, &buf, &len, &flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ozll", &php_sock_res, socket_ce, &buf, &len, &flags) == FAILURE) { RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(php_sock_res), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(php_sock_res); /* overflow check */ if ((len + 1) < 2) { @@ -1428,19 +1457,17 @@ PHP_FUNCTION(socket_send) zend_long len, flags; char *buf; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsll", &arg1, &buf, &buf_len, &len, &flags) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Osll", &arg1, socket_ce, &buf, &buf_len, &len, &flags) == FAILURE) { RETURN_THROWS(); } + php_sock = Z_SOCKET_P(arg1); + if (len < 0) { zend_argument_value_error(3, "must be greater than or equal to 0"); RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } - retval = send(php_sock->bsd_socket, buf, (buf_len < (size_t)len ? buf_len : (size_t)len), flags); if (retval == (size_t)-1) { @@ -1469,13 +1496,11 @@ PHP_FUNCTION(socket_recvfrom) char *address; zend_string *recv_buf; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rzllz|z", &arg1, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ozllz|z", &arg1, socket_ce, &arg2, &arg3, &arg4, &arg5, &arg6) == FAILURE) { RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(arg1); /* overflow check */ /* Shouldthrow ? */ @@ -1585,19 +1610,17 @@ PHP_FUNCTION(socket_sendto) char *buf, *addr; int argc = ZEND_NUM_ARGS(); - if (zend_parse_parameters(argc, "rslls|l", &arg1, &buf, &buf_len, &len, &flags, &addr, &addr_len, &port) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oslls|l", &arg1, socket_ce, &buf, &buf_len, &len, &flags, &addr, &addr_len, &port) == FAILURE) { RETURN_THROWS(); } + php_sock = Z_SOCKET_P(arg1); + if (len < 0) { zend_argument_value_error(3, "must be greater than or equal to 0"); RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } - switch (php_sock->type) { case AF_UNIX: memset(&s_un, 0, sizeof(s_un)); @@ -1667,13 +1690,11 @@ PHP_FUNCTION(socket_get_option) int other_val; zend_long level, optname; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rll", &arg1, &level, &optname) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oll", &arg1, socket_ce, &level, &optname) == FAILURE) { RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(arg1); if (level == IPPROTO_IP) { switch (optname) { @@ -1781,14 +1802,11 @@ PHP_FUNCTION(socket_set_option) zval *l_onoff, *l_linger; zval *sec, *usec; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rllz", &arg1, &level, &optname, &arg4) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ollz", &arg1, socket_ce, &level, &optname, &arg4) == FAILURE) { RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(arg1); set_errno(0); @@ -1935,21 +1953,24 @@ PHP_FUNCTION(socket_create_pair) RETURN_THROWS(); } - php_sock[0] = php_create_socket(); - php_sock[1] = php_create_socket(); + object_init_ex(&retval[0], socket_ce); + php_sock[0] = Z_SOCKET_P(&retval[0]); + + object_init_ex(&retval[1], socket_ce); + php_sock[1] = Z_SOCKET_P(&retval[1]); if (socketpair(domain, type, protocol, fds_array) != 0) { SOCKETS_G(last_error) = errno; php_error_docref(NULL, E_WARNING, "Unable to create socket pair [%d]: %s", errno, sockets_strerror(errno)); - efree(php_sock[0]); - efree(php_sock[1]); + zval_ptr_dtor(&retval[0]); + zval_ptr_dtor(&retval[1]); RETURN_FALSE; } fds_array_zval = zend_try_array_init(fds_array_zval); if (!fds_array_zval) { - efree(php_sock[0]); - efree(php_sock[1]); + zval_ptr_dtor(&retval[0]); + zval_ptr_dtor(&retval[1]); RETURN_THROWS(); } @@ -1962,9 +1983,6 @@ PHP_FUNCTION(socket_create_pair) php_sock[0]->blocking = 1; php_sock[1]->blocking = 1; - ZVAL_RES(&retval[0], zend_register_resource(php_sock[0], le_socket)); - ZVAL_RES(&retval[1], zend_register_resource(php_sock[1], le_socket)); - add_index_zval(fds_array_zval, 0, &retval[0]); add_index_zval(fds_array_zval, 1, &retval[1]); @@ -1981,13 +1999,11 @@ PHP_FUNCTION(socket_shutdown) zend_long how_shutdown = 2; php_socket *php_sock; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &arg1, &how_shutdown) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l", &arg1, socket_ce, &how_shutdown) == FAILURE) { RETURN_THROWS(); } - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(arg1); if (shutdown(php_sock->bsd_socket, how_shutdown) != 0) { PHP_SOCKET_ERROR(php_sock, "Unable to shutdown socket", errno); @@ -2005,14 +2021,12 @@ PHP_FUNCTION(socket_last_error) zval *arg1 = NULL; php_socket *php_sock; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &arg1) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|O!", &arg1, socket_ce) == FAILURE) { RETURN_THROWS(); } if (arg1) { - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(arg1); RETVAL_LONG(php_sock->error); } else { RETVAL_LONG(SOCKETS_G(last_error)); @@ -2026,14 +2040,12 @@ PHP_FUNCTION(socket_clear_error) zval *arg1 = NULL; php_socket *php_sock; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|r", &arg1) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|O!", &arg1, socket_ce) == FAILURE) { RETURN_THROWS(); } if (arg1) { - if ((php_sock = (php_socket *)zend_fetch_resource(Z_RES_P(arg1), le_socket_name, le_socket)) == NULL) { - RETURN_THROWS(); - } + php_sock = Z_SOCKET_P(arg1); php_sock->error = 0; } else { SOCKETS_G(last_error) = 0; @@ -2043,20 +2055,18 @@ PHP_FUNCTION(socket_clear_error) } /* }}} */ -php_socket *socket_import_file_descriptor(PHP_SOCKET socket) +int socket_import_file_descriptor(PHP_SOCKET socket, php_socket *retsock) { #ifdef SO_DOMAIN int type; socklen_t type_len = sizeof(type); #endif - php_socket *retsock; php_sockaddr_storage addr; socklen_t addr_len = sizeof(addr); #ifndef PHP_WIN32 int t; #endif - retsock = php_create_socket(); retsock->bsd_socket = socket; /* determine family */ @@ -2069,7 +2079,7 @@ php_socket *socket_import_file_descriptor(PHP_SOCKET socket) retsock->type = addr.ss_family; } else { PHP_SOCKET_ERROR(retsock, "Unable to obtain socket family", errno); - goto error; + return 0; } /* determine blocking mode */ @@ -2077,17 +2087,13 @@ php_socket *socket_import_file_descriptor(PHP_SOCKET socket) t = fcntl(socket, F_GETFL); if (t == -1) { PHP_SOCKET_ERROR(retsock, "Unable to obtain blocking state", errno); - goto error; + return 0; } else { retsock->blocking = !(t & O_NONBLOCK); } #endif - return retsock; - -error: - efree(retsock); - return NULL; + return 1; } /* {{{ Imports a stream that encapsulates a socket into a socket extension resource. */ @@ -2108,8 +2114,11 @@ PHP_FUNCTION(socket_import_stream) RETURN_FALSE; } - retsock = socket_import_file_descriptor(socket); - if (retsock == NULL) { + object_init_ex(return_value, socket_ce); + retsock = Z_SOCKET_P(return_value); + + if (!socket_import_file_descriptor(socket, retsock)) { + zval_ptr_dtor(return_value); RETURN_FALSE; } @@ -2128,10 +2137,7 @@ PHP_FUNCTION(socket_import_stream) * also be done, but this makes socket_export_stream a bit simpler) */ ZVAL_COPY(&retsock->zstream, zstream); - php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, - PHP_STREAM_BUFFER_NONE, NULL); - - RETURN_RES(zend_register_resource(retsock, le_socket)); + php_stream_set_option(stream, PHP_STREAM_OPTION_READ_BUFFER, PHP_STREAM_BUFFER_NONE, NULL); } /* }}} */ @@ -2145,13 +2151,12 @@ PHP_FUNCTION(socket_export_stream) char *protocol = NULL; size_t protocollen = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &zsocket) == FAILURE) { - RETURN_THROWS(); - } - if ((socket = (php_socket *) zend_fetch_resource(Z_RES_P(zsocket), le_socket_name, le_socket)) == NULL) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zsocket, socket_ce) == FAILURE) { RETURN_THROWS(); } + socket = Z_SOCKET_P(zsocket); + /* Either we already exported a stream or the socket came from an import, * just return the existing stream */ if (!Z_ISUNDEF(socket->zstream)) { @@ -2239,14 +2244,15 @@ PHP_FUNCTION(socket_addrinfo_lookup) zend_string *hostname, *key; zval *hint, *zhints = NULL; - struct addrinfo hints, *result, *rp, *res; - - memset(&hints, 0, sizeof(hints)); + struct addrinfo hints, *result, *rp; + php_addrinfo *res; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|sa", &hostname, &service, &service_len, &zhints) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|s!a", &hostname, &service, &service_len, &zhints) == FAILURE) { RETURN_THROWS(); } + memset(&hints, 0, sizeof(hints)); + if (zhints) { ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(zhints), key, hint) { if (key) { @@ -2274,17 +2280,19 @@ PHP_FUNCTION(socket_addrinfo_lookup) for (rp = result; rp != NULL; rp = rp->ai_next) { if (rp->ai_family != AF_UNSPEC) { - res = emalloc(sizeof(struct addrinfo)); - memcpy(res, rp, sizeof(struct addrinfo)); + zval zaddr; - res->ai_addr = emalloc(rp->ai_addrlen); - memcpy(res->ai_addr, rp->ai_addr, rp->ai_addrlen); + object_init_ex(&zaddr, address_info_ce); + res = Z_ADDRESS_INFO_P(&zaddr); + + res->addrinfo->ai_addr = emalloc(rp->ai_addrlen); + memcpy(res->addrinfo->ai_addr, rp->ai_addr, rp->ai_addrlen); if (rp->ai_canonname != NULL) { - res->ai_canonname = estrdup(rp->ai_canonname); + res->addrinfo->ai_canonname = estrdup(rp->ai_canonname); } - add_next_index_resource(return_value, zend_register_resource(res, le_addrinfo)); + add_next_index_zval(return_value, &zaddr); } } @@ -2297,25 +2305,25 @@ PHP_FUNCTION(socket_addrinfo_bind) { zval *arg1; int retval; - struct addrinfo *ai; + php_addrinfo *ai; php_socket *php_sock; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg1) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &arg1, address_info_ce) == FAILURE) { RETURN_THROWS(); } - if ((ai = (struct addrinfo *) zend_fetch_resource(Z_RES_P(arg1), le_addrinfo_name, le_addrinfo)) == NULL) { - RETURN_THROWS(); - } + ai = Z_ADDRESS_INFO_P(arg1); - php_sock = php_create_socket(); - php_sock->bsd_socket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - php_sock->type = ai->ai_family; + object_init_ex(return_value, socket_ce); + php_sock = Z_SOCKET_P(return_value); + + php_sock->bsd_socket = socket(ai->addrinfo->ai_family, ai->addrinfo->ai_socktype, ai->addrinfo->ai_protocol); + php_sock->type = ai->addrinfo->ai_family; if (IS_INVALID_SOCKET(php_sock)) { SOCKETS_G(last_error) = errno; php_error_docref(NULL, E_WARNING, "Unable to create socket [%d]: %s", errno, sockets_strerror(errno)); - efree(php_sock); + zval_ptr_dtor(return_value); RETURN_FALSE; } @@ -2327,7 +2335,7 @@ PHP_FUNCTION(socket_addrinfo_bind) { // AF_UNIX sockets via getaddrino are not implemented due to security problems close(php_sock->bsd_socket); - efree(php_sock); + zval_ptr_dtor(return_value); RETURN_FALSE; } @@ -2336,12 +2344,12 @@ PHP_FUNCTION(socket_addrinfo_bind) case AF_INET6: #endif { - retval = bind(php_sock->bsd_socket, ai->ai_addr, ai->ai_addrlen); + retval = bind(php_sock->bsd_socket, ai->addrinfo->ai_addr, ai->addrinfo->ai_addrlen); break; } default: close(php_sock->bsd_socket); - efree(php_sock); + zval_ptr_dtor(return_value); zend_argument_value_error(1, "must be either AF_UNIX, AF_INET, or AF_INET6"); RETURN_THROWS(); } @@ -2349,11 +2357,9 @@ PHP_FUNCTION(socket_addrinfo_bind) if (retval != 0) { PHP_SOCKET_ERROR(php_sock, "Unable to bind address", errno); close(php_sock->bsd_socket); - efree(php_sock); + zval_ptr_dtor(return_value); RETURN_FALSE; } - - RETURN_RES(zend_register_resource(php_sock, le_socket)); } /* }}} */ @@ -2362,25 +2368,25 @@ PHP_FUNCTION(socket_addrinfo_connect) { zval *arg1; int retval; - struct addrinfo *ai; + php_addrinfo *ai; php_socket *php_sock; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg1) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &arg1, address_info_ce) == FAILURE) { RETURN_THROWS(); } - if ((ai = (struct addrinfo *) zend_fetch_resource(Z_RES_P(arg1), le_addrinfo_name, le_addrinfo)) == NULL) { - RETURN_THROWS(); - } + ai = Z_ADDRESS_INFO_P(arg1); + + object_init_ex(return_value, socket_ce); + php_sock = Z_SOCKET_P(return_value); - php_sock = php_create_socket(); - php_sock->bsd_socket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - php_sock->type = ai->ai_family; + php_sock->bsd_socket = socket(ai->addrinfo->ai_family, ai->addrinfo->ai_socktype, ai->addrinfo->ai_protocol); + php_sock->type = ai->addrinfo->ai_family; if (IS_INVALID_SOCKET(php_sock)) { SOCKETS_G(last_error) = errno; php_error_docref(NULL, E_WARNING, "Unable to create socket [%d]: %s", errno, sockets_strerror(errno)); - efree(php_sock); + zval_ptr_dtor(return_value); RETURN_FALSE; } @@ -2392,7 +2398,7 @@ PHP_FUNCTION(socket_addrinfo_connect) { // AF_UNIX sockets via getaddrino are not implemented due to security problems close(php_sock->bsd_socket); - efree(php_sock); + zval_ptr_dtor(return_value); RETURN_FALSE; } @@ -2401,24 +2407,22 @@ PHP_FUNCTION(socket_addrinfo_connect) case AF_INET6: #endif { - retval = connect(php_sock->bsd_socket, ai->ai_addr, ai->ai_addrlen); + retval = connect(php_sock->bsd_socket, ai->addrinfo->ai_addr, ai->addrinfo->ai_addrlen); break; } default: zend_argument_value_error(1, "socket type must be either AF_UNIX, AF_INET, or AF_INET6"); close(php_sock->bsd_socket); - efree(php_sock); + zval_ptr_dtor(return_value); RETURN_THROWS(); } if (retval != 0) { PHP_SOCKET_ERROR(php_sock, "Unable to connect address", errno); close(php_sock->bsd_socket); - efree(php_sock); + zval_ptr_dtor(return_value); RETURN_FALSE; } - - RETURN_RES(zend_register_resource(php_sock, le_socket)); } /* }}} */ @@ -2426,46 +2430,44 @@ PHP_FUNCTION(socket_addrinfo_connect) PHP_FUNCTION(socket_addrinfo_explain) { zval *arg1, sockaddr; - struct addrinfo *ai; + php_addrinfo *ai; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &arg1) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &arg1, address_info_ce) == FAILURE) { RETURN_THROWS(); } - if ((ai = (struct addrinfo *) zend_fetch_resource(Z_RES_P(arg1), le_addrinfo_name, le_addrinfo)) == NULL) { - RETURN_THROWS(); - } + ai = Z_ADDRESS_INFO_P(arg1); array_init(return_value); - add_assoc_long(return_value, "ai_flags", ai->ai_flags); - add_assoc_long(return_value, "ai_family", ai->ai_family); - add_assoc_long(return_value, "ai_socktype", ai->ai_socktype); - add_assoc_long(return_value, "ai_protocol", ai->ai_protocol); - if (ai->ai_canonname != NULL) { - add_assoc_string(return_value, "ai_canonname", ai->ai_canonname); + add_assoc_long(return_value, "ai_flags", ai->addrinfo->ai_flags); + add_assoc_long(return_value, "ai_family", ai->addrinfo->ai_family); + add_assoc_long(return_value, "ai_socktype", ai->addrinfo->ai_socktype); + add_assoc_long(return_value, "ai_protocol", ai->addrinfo->ai_protocol); + if (ai->addrinfo->ai_canonname != NULL) { + add_assoc_string(return_value, "ai_canonname", ai->addrinfo->ai_canonname); } array_init(&sockaddr); - switch(ai->ai_family) { + switch(ai->addrinfo->ai_family) { case AF_INET: { - struct sockaddr_in *sa = (struct sockaddr_in *) ai->ai_addr; + struct sockaddr_in *sa = (struct sockaddr_in *) ai->addrinfo->ai_addr; char addr[INET_ADDRSTRLEN]; add_assoc_long(&sockaddr, "sin_port", ntohs((unsigned short) sa->sin_port)); - inet_ntop(ai->ai_family, &sa->sin_addr, addr, sizeof(addr)); + inet_ntop(ai->addrinfo->ai_family, &sa->sin_addr, addr, sizeof(addr)); add_assoc_string(&sockaddr, "sin_addr", addr); break; } #if HAVE_IPV6 case AF_INET6: { - struct sockaddr_in6 *sa = (struct sockaddr_in6 *) ai->ai_addr; + struct sockaddr_in6 *sa = (struct sockaddr_in6 *) ai->addrinfo->ai_addr; char addr[INET6_ADDRSTRLEN]; add_assoc_long(&sockaddr, "sin6_port", ntohs((unsigned short) sa->sin6_port)); - inet_ntop(ai->ai_family, &sa->sin6_addr, addr, sizeof(addr)); + inet_ntop(ai->addrinfo->ai_family, &sa->sin6_addr, addr, sizeof(addr)); add_assoc_string(&sockaddr, "sin6_addr", addr); break; } @@ -2488,13 +2490,12 @@ PHP_FUNCTION(socket_wsaprotocol_info_export) zend_string *seg_name; HANDLE map; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &zsocket, &target_pid) == FAILURE) { - RETURN_THROWS(); - } - if ((socket = (php_socket *) zend_fetch_resource(Z_RES_P(zsocket), le_socket_name, le_socket)) == NULL) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &arg1, socket_ce, &target_pid) == FAILURE) { RETURN_THROWS(); } + socket = Z_SOCKET_P(arg1); + if (SOCKET_ERROR == WSADuplicateSocket(socket->bsd_socket, (DWORD)target_pid, &wi)) { DWORD err = WSAGetLastError(); char *buf = php_win32_error_to_msg(err); @@ -2581,13 +2582,13 @@ PHP_FUNCTION(socket_wsaprotocol_info_import) RETURN_FALSE; } - php_sock = php_create_socket(); + object_init_ex(return_value, socket_ce); + php_sock = Z_SOCKET_P(return_value); + php_sock->bsd_socket = sock; php_sock->type = wi.iAddressFamily; php_sock->error = 0; php_sock->blocking = 1; - - RETURN_RES(zend_register_resource(php_sock, le_socket)); } /* }}} */ diff --git a/ext/sockets/sockets.stub.php b/ext/sockets/sockets.stub.php index 680a1b883559f..99dae765ad7b7 100644 --- a/ext/sockets/sockets.stub.php +++ b/ext/sockets/sockets.stub.php @@ -2,140 +2,117 @@ /** @generate-function-entries */ +final class Socket +{ +} + +final class AddressInfo +{ +} + function socket_select(?array &$read_fds, ?array &$write_fds, ?array &$except_fds, ?int $tv_sec, int $tv_usec = 0): int|false {} -/** @return resource|false */ -function socket_create_listen(int $port, int $backlog = 128) {} +function socket_create_listen(int $port, int $backlog = 128): Socket|false {} -/** - * @param resource $socket - * @return resource|false - */ -function socket_accept($socket) {} +function socket_accept(Socket $socket): Socket|false {} -/** @param resource $socket */ -function socket_set_nonblock($socket): bool {} +function socket_set_nonblock(Socket $socket): bool {} -/** @param resource $socket */ -function socket_set_block($socket): bool {} +function socket_set_block(Socket $socket): bool {} -/** @param resource $socket */ -function socket_listen($socket, int $backlog = 0): bool {} +function socket_listen(Socket $socket, int $backlog = 0): bool {} -/** @param resource $socket */ -function socket_close($socket): void {} +/** @deprecated */ +function socket_close(Socket $socket): void {} -/** @param resource $socket */ -function socket_write($socket, string $buf, int $length = UNKNOWN): int|false {} +function socket_write(Socket $socket, string $buf, ?int $length = null): int|false {} -/** @param resource $socket */ -function socket_read($socket, int $length, int $type = PHP_BINARY_READ): string|false {} +function socket_read(Socket $socket, int $length, int $type = PHP_BINARY_READ): string|false {} -/** @param resource $socket */ -function socket_getsockname($socket, &$addr, &$port = UNKNOWN): bool {} +/** + * @param string $addr + * @param int $port + */ +function socket_getsockname(Socket $socket, &$addr, &$port = UNKNOWN): bool {} -/** @param resource $socket */ -function socket_getpeername($socket, &$addr, &$port = UNKNOWN): bool {} +/** + * @param string $addr + * @param int $port + */ +function socket_getpeername(Socket $socket, &$addr, &$port = UNKNOWN): bool {} -/** @return resource|false */ -function socket_create(int $domain, int $type, int $protocol) {} +function socket_create(int $domain, int $type, int $protocol): Socket|false {} -/** @param resource $socket */ -function socket_connect($socket, string $addr, int $port = UNKNOWN): bool {} +function socket_connect(Socket $socket, string $addr, ?int $port = null): bool {} function socket_strerror(int $errno): string {} -/** @param resource $socket */ -function socket_bind($socket, string $addr, int $port = 0): bool {} +function socket_bind(Socket $socket, string $addr, int $port = 0): bool {} -/** @param resource $socket */ -function socket_recv($socket, &$buf, int $len, int $flags): int|false {} +function socket_recv(Socket $socket, &$buf, int $len, int $flags): int|false {} -/** @param resource $socket */ -function socket_send($socket, string $buf, int $len, int $flags): int|false {} +function socket_send(Socket $socket, string $buf, int $len, int $flags): int|false {} -/** @param resource $socket */ -function socket_recvfrom($socket, &$buf, int $len, int $flags, &$name, &$port = UNKNOWN): int|false {} +/** + * @param string $buf + * @param string $name + * @param int $port + */ +function socket_recvfrom(Socket $socket, &$buf, int $len, int $flags, &$name, &$port = UNKNOWN): int|false {} -/** @param resource $socket */ -function socket_sendto($socket, string $buf, int $len, int $flags, string $addr, int $port = 0): int|false {} +function socket_sendto(Socket $socket, string $buf, int $len, int $flags, string $addr, int $port = 0): int|false {} -/** @param resource $socket */ -function socket_get_option($socket, int $level, int $optname): array|int|false {} +function socket_get_option(Socket $socket, int $level, int $optname): array|int|false {} -/** - * @param resource $socket - * @alias socket_get_option - */ -function socket_getopt($socket, int $level, int $optname): array|int|false {} +/** @alias socket_get_option */ +function socket_getopt(Socket $socket, int $level, int $optname): array|int|false {} -/** @param resource $socket */ -function socket_set_option($socket, int $level, int $optname, $optval): bool {} +/** @param array|string|int $optval */ +function socket_set_option(Socket $socket, int $level, int $optname, $optval): bool {} /** - * @param resource $socket + * @param array|string|int $optval * @alias socket_set_option */ -function socket_setopt($socket, int $level, int $optname, $optval): bool {} +function socket_setopt(Socket $socket, int $level, int $optname, $optval): bool {} #ifdef HAVE_SOCKETPAIR +/** @param array $fd */ function socket_create_pair(int $domain, int $type, int $protocol, &$fd): bool|null {} #endif #ifdef HAVE_SHUTDOWN -/** @param resource $socket */ -function socket_shutdown($socket, int $how = 2): bool {} +function socket_shutdown(Socket $socket, int $how = 2): bool {} #endif -/** @param resource $socket */ -function socket_last_error($socket = UNKNOWN): int {} +function socket_last_error(?Socket $socket = null): int {} -/** @param resource $socket */ -function socket_clear_error($socket = UNKNOWN): void {} +function socket_clear_error(?Socket $socket = null): void {} -/** - * @param resource $stream - * @return resource|false - */ -function socket_import_stream($stream) {} +/** @param resource $stream */ +function socket_import_stream($stream): Socket|false {} -/** - * @param resource $socket - * @return resource|false - */ -function socket_export_stream($socket) {} +/** @return resource|false */ +function socket_export_stream(Socket $socket) {} -/** @param resource $socket */ -function socket_sendmsg($socket, array $msghdr, int $flags = 0): int|false {} +function socket_sendmsg(Socket $socket, array $msghdr, int $flags = 0): int|false {} -/** @param resource $socket */ -function socket_recvmsg($socket, array &$msghdr, int $flags = 0): int|false {} +function socket_recvmsg(Socket $socket, array &$msghdr, int $flags = 0): int|false {} function socket_cmsg_space(int $level, int $type, int $n = 0): ?int {} -function socket_addrinfo_lookup(string $host, string $service = UNKNOWN, array $hints = UNKNOWN): array|false {} +function socket_addrinfo_lookup(string $host, ?string $service = null, array $hints = []): array|false {} -/** - * @param resource $addr - * @return resource|false - */ -function socket_addrinfo_connect($addr) {} +function socket_addrinfo_connect(AddressInfo $addr): Socket|false {} -/** - * @param resource $addr - * @return resource|false - */ -function socket_addrinfo_bind($addr) {} +function socket_addrinfo_bind(AddressInfo $addr): Socket|false {} -/** @param resource $addr */ -function socket_addrinfo_explain($addr): array {} +function socket_addrinfo_explain(AddressInfo $addr): array {} #ifdef PHP_WIN32 -/** @param resource $socket */ -function socket_wsaprotocol_info_export($socket, int $target_pid): string|false {} +function socket_wsaprotocol_info_export(Socket $socket, int $target_pid): string|false {} -/** @return resource|false */ -function socket_wsaprotocol_info_import(string $info_id) {} +function socket_wsaprotocol_info_import(string $info_id): Socket|false {} function socket_wsaprotocol_info_release(string $info_id): bool {} #endif diff --git a/ext/sockets/sockets_arginfo.h b/ext/sockets/sockets_arginfo.h index 36aa16733e17e..855e24094a34a 100644 --- a/ext/sockets/sockets_arginfo.h +++ b/ext/sockets/sockets_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 4494f9f246dbc98047d97d913cc1add9f91eb0ff */ + * Stub hash: 1b2cbff950087492186cb8c216864b6e51abcf28 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_select, 0, 4, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(1, read_fds, IS_ARRAY, 1) @@ -9,60 +9,60 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_select, 0, 4, MAY_BE_LONG ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, tv_usec, IS_LONG, 0, "0") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create_listen, 0, 0, 1) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_socket_create_listen, 0, 1, Socket, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, backlog, IS_LONG, 0, "128") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_accept, 0, 0, 1) - ZEND_ARG_INFO(0, socket) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_socket_accept, 0, 1, Socket, MAY_BE_FALSE) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_socket_set_nonblock, 0, 1, _IS_BOOL, 0) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_END_ARG_INFO() #define arginfo_socket_set_block arginfo_socket_set_nonblock ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_socket_listen, 0, 1, _IS_BOOL, 0) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, backlog, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_socket_close, 0, 1, IS_VOID, 0) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_write, 0, 2, MAY_BE_LONG|MAY_BE_FALSE) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_TYPE_INFO(0, buf, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, length, IS_LONG, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, length, IS_LONG, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_read, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_TYPE_INFO(0, length, IS_LONG, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, type, IS_LONG, 0, "PHP_BINARY_READ") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_socket_getsockname, 0, 2, _IS_BOOL, 0) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_INFO(1, addr) ZEND_ARG_INFO(1, port) ZEND_END_ARG_INFO() #define arginfo_socket_getpeername arginfo_socket_getsockname -ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_create, 0, 0, 3) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_socket_create, 0, 3, Socket, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, domain, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, protocol, IS_LONG, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_socket_connect, 0, 2, _IS_BOOL, 0) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_TYPE_INFO(0, addr, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, port, IS_LONG, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, port, IS_LONG, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_socket_strerror, 0, 1, IS_STRING, 0) @@ -70,27 +70,27 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_socket_strerror, 0, 1, IS_STRING ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_socket_bind, 0, 2, _IS_BOOL, 0) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_TYPE_INFO(0, addr, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, port, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_recv, 0, 4, MAY_BE_LONG|MAY_BE_FALSE) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_INFO(1, buf) ZEND_ARG_TYPE_INFO(0, len, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_send, 0, 4, MAY_BE_LONG|MAY_BE_FALSE) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_TYPE_INFO(0, buf, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, len, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_recvfrom, 0, 5, MAY_BE_LONG|MAY_BE_FALSE) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_INFO(1, buf) ZEND_ARG_TYPE_INFO(0, len, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0) @@ -99,7 +99,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_recvfrom, 0, 5, MAY_BE_LO ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_sendto, 0, 5, MAY_BE_LONG|MAY_BE_FALSE) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_TYPE_INFO(0, buf, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, len, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0) @@ -108,7 +108,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_sendto, 0, 5, MAY_BE_LONG ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_get_option, 0, 3, MAY_BE_ARRAY|MAY_BE_LONG|MAY_BE_FALSE) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_TYPE_INFO(0, level, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, optname, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -116,7 +116,7 @@ ZEND_END_ARG_INFO() #define arginfo_socket_getopt arginfo_socket_get_option ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_socket_set_option, 0, 4, _IS_BOOL, 0) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_TYPE_INFO(0, level, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, optname, IS_LONG, 0) ZEND_ARG_INFO(0, optval) @@ -135,33 +135,35 @@ ZEND_END_ARG_INFO() #if defined(HAVE_SHUTDOWN) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_socket_shutdown, 0, 1, _IS_BOOL, 0) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, how, IS_LONG, 0, "2") ZEND_END_ARG_INFO() #endif ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_socket_last_error, 0, 0, IS_LONG, 0) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, socket, Socket, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_socket_clear_error, 0, 0, IS_VOID, 0) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, socket, Socket, 1, "null") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_import_stream, 0, 0, 1) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_socket_import_stream, 0, 1, Socket, MAY_BE_FALSE) ZEND_ARG_INFO(0, stream) ZEND_END_ARG_INFO() -#define arginfo_socket_export_stream arginfo_socket_accept +ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_export_stream, 0, 0, 1) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_sendmsg, 0, 2, MAY_BE_LONG|MAY_BE_FALSE) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_TYPE_INFO(0, msghdr, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_recvmsg, 0, 2, MAY_BE_LONG|MAY_BE_FALSE) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_TYPE_INFO(1, msghdr, IS_ARRAY, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0") ZEND_END_ARG_INFO() @@ -174,29 +176,29 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_addrinfo_lookup, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, host, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, service, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, hints, IS_ARRAY, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, service, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, hints, IS_ARRAY, 0, "[]") ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_addrinfo_connect, 0, 0, 1) - ZEND_ARG_INFO(0, addr) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_socket_addrinfo_connect, 0, 1, Socket, MAY_BE_FALSE) + ZEND_ARG_OBJ_INFO(0, addr, AddressInfo, 0) ZEND_END_ARG_INFO() #define arginfo_socket_addrinfo_bind arginfo_socket_addrinfo_connect ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_socket_addrinfo_explain, 0, 1, IS_ARRAY, 0) - ZEND_ARG_INFO(0, addr) + ZEND_ARG_OBJ_INFO(0, addr, AddressInfo, 0) ZEND_END_ARG_INFO() #if defined(PHP_WIN32) ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_wsaprotocol_info_export, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) - ZEND_ARG_INFO(0, socket) + ZEND_ARG_OBJ_INFO(0, socket, Socket, 0) ZEND_ARG_TYPE_INFO(0, target_pid, IS_LONG, 0) ZEND_END_ARG_INFO() #endif #if defined(PHP_WIN32) -ZEND_BEGIN_ARG_INFO_EX(arginfo_socket_wsaprotocol_info_import, 0, 0, 1) +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_socket_wsaprotocol_info_import, 0, 1, Socket, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, info_id, IS_STRING, 0) ZEND_END_ARG_INFO() #endif @@ -264,7 +266,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(socket_set_nonblock, arginfo_socket_set_nonblock) ZEND_FE(socket_set_block, arginfo_socket_set_block) ZEND_FE(socket_listen, arginfo_socket_listen) - ZEND_FE(socket_close, arginfo_socket_close) + ZEND_DEP_FE(socket_close, arginfo_socket_close) ZEND_FE(socket_write, arginfo_socket_write) ZEND_FE(socket_read, arginfo_socket_read) ZEND_FE(socket_getsockname, arginfo_socket_getsockname) @@ -309,3 +311,13 @@ static const zend_function_entry ext_functions[] = { #endif ZEND_FE_END }; + + +static const zend_function_entry class_Socket_methods[] = { + ZEND_FE_END +}; + + +static const zend_function_entry class_AddressInfo_methods[] = { + ZEND_FE_END +}; diff --git a/ext/sockets/tests/bug76839.phpt b/ext/sockets/tests/bug76839.phpt index 49aff731f70ca..65d57321c9716 100644 --- a/ext/sockets/tests/bug76839.phpt +++ b/ext/sockets/tests/bug76839.phpt @@ -37,9 +37,9 @@ for ($i = 0; $i < 10; $i++) { socket_sendto($receiverSocket, 'Pong!', 5, 0, $from); echo "Responded to sender with 'Pong!'\n"; - socket_close($receiverSocket); + @socket_close($receiverSocket); unlink($receiverSocketPath); - socket_close($senderSocket); + @socket_close($senderSocket); unlink($senderSocketPath); } --EXPECT-- diff --git a/ext/sockets/tests/ipv4loop.phpt b/ext/sockets/tests/ipv4loop.phpt index 4e5d15453bc4a..1f3a22b8cb6ef 100644 --- a/ext/sockets/tests/ipv4loop.phpt +++ b/ext/sockets/tests/ipv4loop.phpt @@ -51,3 +51,9 @@ IPv4 Loopback test --EXPECT-- string(10) "ABCdef123 " + +Deprecated: Function socket_close() is deprecated + +Deprecated: Function socket_close() is deprecated + +Deprecated: Function socket_close() is deprecated diff --git a/ext/sockets/tests/ipv6loop.phpt b/ext/sockets/tests/ipv6loop.phpt index 109da5bc2db28..3c04f8588321a 100644 --- a/ext/sockets/tests/ipv6loop.phpt +++ b/ext/sockets/tests/ipv6loop.phpt @@ -55,3 +55,9 @@ IPv6 Loopback test --EXPECT-- string(10) "ABCdef123 " + +Deprecated: Function socket_close() is deprecated + +Deprecated: Function socket_close() is deprecated + +Deprecated: Function socket_close() is deprecated diff --git a/ext/sockets/tests/mcast_ipv4_recv.phpt b/ext/sockets/tests/mcast_ipv4_recv.phpt index 16e2e91b62c46..28237f415ed03 100644 --- a/ext/sockets/tests/mcast_ipv4_recv.phpt +++ b/ext/sockets/tests/mcast_ipv4_recv.phpt @@ -158,7 +158,8 @@ bool(true) creating unbound socket and hoping the routing table causes an interface other than lo to be used for sending messages to 224.0.0.23 bool(true) creating receive socket -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} bool(true) bool(true) int(14) diff --git a/ext/sockets/tests/mcast_ipv6_recv.phpt b/ext/sockets/tests/mcast_ipv6_recv.phpt index 10233b49a57ea..3bc791a451a1c 100644 --- a/ext/sockets/tests/mcast_ipv6_recv.phpt +++ b/ext/sockets/tests/mcast_ipv6_recv.phpt @@ -180,9 +180,11 @@ if ($i == 8) { } --EXPECTF-- creating send socket -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} creating receive socket -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} bool(true) bool(true) int(14) diff --git a/ext/sockets/tests/mcast_ipv6_recv_limited.phpt b/ext/sockets/tests/mcast_ipv6_recv_limited.phpt index 87b38c144c1c3..dda3756b7ea57 100644 --- a/ext/sockets/tests/mcast_ipv6_recv_limited.phpt +++ b/ext/sockets/tests/mcast_ipv6_recv_limited.phpt @@ -108,9 +108,11 @@ if ($i == 3) { } --EXPECTF-- creating send socket -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} creating receive socket -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} bool(true) bool(true) int(14) diff --git a/ext/sockets/tests/socket_addrinfo_bind.phpt b/ext/sockets/tests/socket_addrinfo_bind.phpt index eb15afee25ac6..59259728689c2 100644 --- a/ext/sockets/tests/socket_addrinfo_bind.phpt +++ b/ext/sockets/tests/socket_addrinfo_bind.phpt @@ -13,6 +13,7 @@ $addrinfo = socket_addrinfo_lookup('127.0.0.1', 2000, array( )); var_dump(socket_addrinfo_bind($addrinfo[0])); echo "Done"; ---EXPECTF-- -resource(%d) of type (Socket) +--EXPECT-- +object(Socket)#1 (0) { +} Done diff --git a/ext/sockets/tests/socket_addrinfo_connect.phpt b/ext/sockets/tests/socket_addrinfo_connect.phpt index 009d54839b7d0..f162449b9a4a8 100644 --- a/ext/sockets/tests/socket_addrinfo_connect.phpt +++ b/ext/sockets/tests/socket_addrinfo_connect.phpt @@ -13,6 +13,7 @@ $addrinfo = socket_addrinfo_lookup('127.0.0.1', 2000, array( )); var_dump(socket_addrinfo_connect($addrinfo[0])); echo "Done"; ---EXPECTF-- -resource(%d) of type (Socket) +--EXPECT-- +object(Socket)#1 (0) { +} Done diff --git a/ext/sockets/tests/socket_addrinfo_lookup.phpt b/ext/sockets/tests/socket_addrinfo_lookup.phpt index 5ecd945f71079..8393eaa7efb9b 100644 --- a/ext/sockets/tests/socket_addrinfo_lookup.phpt +++ b/ext/sockets/tests/socket_addrinfo_lookup.phpt @@ -16,5 +16,6 @@ var_dump($addrinfo[0]); echo "Done"; --EXPECTF-- Notice: socket_addrinfo_lookup(): Unknown hint invalid in %ssocket_addrinfo_lookup.php on line %d -resource(%d) of type (AddressInfo) +object(AddressInfo)#%d (0) { +} Done diff --git a/ext/sockets/tests/socket_cmsg_credentials.phpt b/ext/sockets/tests/socket_cmsg_credentials.phpt index 09266e6cbd968..50663d733ef72 100644 --- a/ext/sockets/tests/socket_cmsg_credentials.phpt +++ b/ext/sockets/tests/socket_cmsg_credentials.phpt @@ -58,14 +58,16 @@ $pid = getmypid(); var_dump($data['control'][0]['data']['pid'] === $pid); --EXPECTF-- creating send socket -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} creating receive socket -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} bool(true) int(5) Array ( - [name] => + [name] => [control] => Array ( [0] => Array diff --git a/ext/sockets/tests/socket_cmsg_rights.phpt b/ext/sockets/tests/socket_cmsg_rights.phpt index bd758abdf97aa..f84bc810635fe 100644 --- a/ext/sockets/tests/socket_cmsg_rights.phpt +++ b/ext/sockets/tests/socket_cmsg_rights.phpt @@ -61,7 +61,7 @@ if ($data["control"]) { if ($control["level"] == SOL_SOCKET && $control["type"] == SCM_RIGHTS) { foreach ($control["data"] as $resource) { - if (!is_resource($resource)) { + if (!is_object($resource)) { echo "FAIL RES\n"; var_dump($data); exit; @@ -79,9 +79,11 @@ if ($data["control"]) { } --EXPECTF-- creating send socket -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} creating receive socket -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} bool(true) int(11) array(3) { diff --git a/ext/sockets/tests/socket_create_listen_used.phpt b/ext/sockets/tests/socket_create_listen_used.phpt index 2dfec4fbf7968..5e5c587188a49 100644 --- a/ext/sockets/tests/socket_create_listen_used.phpt +++ b/ext/sockets/tests/socket_create_listen_used.phpt @@ -21,7 +21,8 @@ fa@php.net socket_close($s_c_l); ?> --EXPECTF-- -resource(%i) of type (Socket) +object(Socket)#%d (0) { +} Warning: socket_create_listen(): unable to bind to given address [%i]: %a in %s on line %d bool(false) diff --git a/ext/sockets/tests/socket_create_pair.phpt b/ext/sockets/tests/socket_create_pair.phpt index 6af6e42f20223..604d5a2319044 100644 --- a/ext/sockets/tests/socket_create_pair.phpt +++ b/ext/sockets/tests/socket_create_pair.phpt @@ -18,7 +18,9 @@ var_dump($sockets); --EXPECT-- array(2) { [0]=> - resource(4) of type (Socket) + object(Socket)#1 (0) { + } [1]=> - resource(5) of type (Socket) + object(Socket)#2 (0) { + } } diff --git a/ext/sockets/tests/socket_export_stream-2.phpt b/ext/sockets/tests/socket_export_stream-2.phpt index 65a2a7f7559f1..4e2a632d4601b 100644 --- a/ext/sockets/tests/socket_export_stream-2.phpt +++ b/ext/sockets/tests/socket_export_stream-2.phpt @@ -33,6 +33,7 @@ echo "Done."; --EXPECTF-- socket_export_stream(): supplied resource is not a valid Socket resource socket_export_stream(): supplied resource is not a valid Socket resource -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} socket_export_stream(): supplied resource is not a valid Socket resource Done. diff --git a/ext/sockets/tests/socket_export_stream-3.phpt b/ext/sockets/tests/socket_export_stream-3.phpt index ac48d865b9eec..ed3b7f83e5a45 100644 --- a/ext/sockets/tests/socket_export_stream-3.phpt +++ b/ext/sockets/tests/socket_export_stream-3.phpt @@ -40,7 +40,8 @@ echo "Done.\n"; --EXPECTF-- resource(%d) of type (stream) bool(true) -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} int(10) string(10) "my message" Done. diff --git a/ext/sockets/tests/socket_import_stream-1.phpt b/ext/sockets/tests/socket_import_stream-1.phpt index 925966312da26..8608af33d4b06 100644 --- a/ext/sockets/tests/socket_import_stream-1.phpt +++ b/ext/sockets/tests/socket_import_stream-1.phpt @@ -21,5 +21,6 @@ socket_close($sock); var_dump(stream_get_contents($s1)); --EXPECTF-- -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} string(12) "test message" diff --git a/ext/sockets/tests/socket_import_stream-3.phpt b/ext/sockets/tests/socket_import_stream-3.phpt index 4f8668ec872d7..6f340a4e6cdd3 100644 --- a/ext/sockets/tests/socket_import_stream-3.phpt +++ b/ext/sockets/tests/socket_import_stream-3.phpt @@ -37,9 +37,11 @@ stream_set_blocking($stream, 0); var_dump(fread($stream, strlen($m))); echo "Done.\n"; --EXPECTF-- -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} bool(true) -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} int(10) string(10) "my message" Done. diff --git a/ext/sockets/tests/socket_recvmsg.phpt b/ext/sockets/tests/socket_recvmsg.phpt index 2d7a2f0d694c9..21f7b730587e9 100644 --- a/ext/sockets/tests/socket_recvmsg.phpt +++ b/ext/sockets/tests/socket_recvmsg.phpt @@ -49,10 +49,12 @@ if (!socket_recvmsg($s, $data, 0)) die("recvmsg"); print_r($data); --EXPECTF-- creating send socket -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} bool(true) creating receive socket -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} bool(true) int(14) Array diff --git a/ext/sockets/tests/socket_sendrecvmsg_multi_msg-unix.phpt b/ext/sockets/tests/socket_sendrecvmsg_multi_msg-unix.phpt index 2de272356a133..107aa626e81c9 100644 --- a/ext/sockets/tests/socket_sendrecvmsg_multi_msg-unix.phpt +++ b/ext/sockets/tests/socket_sendrecvmsg_multi_msg-unix.phpt @@ -62,10 +62,12 @@ if (!socket_recvmsg($s, $data, 0)) die("recvmsg"); print_r($data); --EXPECTF-- creating send socket -resource(5) of type (Socket) +object(Socket)#%d (0) { +} bool(true) creating receive socket -resource(6) of type (Socket) +object(Socket)#%d (0) { +} bool(true) int(11) Array diff --git a/ext/sockets/tests/socket_sendrecvmsg_multi_msg.phpt b/ext/sockets/tests/socket_sendrecvmsg_multi_msg.phpt index ff61d3a230dd9..b4ba00debe414 100644 --- a/ext/sockets/tests/socket_sendrecvmsg_multi_msg.phpt +++ b/ext/sockets/tests/socket_sendrecvmsg_multi_msg.phpt @@ -56,10 +56,12 @@ if (!socket_recvmsg($s, $data, 0)) die("recvmsg"); print_r($data); --EXPECTF-- creating send socket -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} bool(true) creating receive socket -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} bool(true) int(11) Array diff --git a/ext/sockets/tests/socket_set_nonblock.phpt b/ext/sockets/tests/socket_set_nonblock.phpt index 88f29d928e8d5..46d673232e1ac 100644 --- a/ext/sockets/tests/socket_set_nonblock.phpt +++ b/ext/sockets/tests/socket_set_nonblock.phpt @@ -17,5 +17,6 @@ fa@php.net //socket_accept($s_c_l); socket_close($s_c_l); ?> ---EXPECTF-- -resource(%i) of type (Socket) +--EXPECT-- +object(Socket)#1 (0) { +} diff --git a/ext/sockets/tests/wsaprotocol_info_0.phpt b/ext/sockets/tests/wsaprotocol_info_0.phpt index 3e251914ed0ac..efe1728f838ed 100644 --- a/ext/sockets/tests/wsaprotocol_info_0.phpt +++ b/ext/sockets/tests/wsaprotocol_info_0.phpt @@ -48,9 +48,12 @@ if (!extension_loaded('sockets')) { ?> --EXPECTF-- bool(true) -resource(%d) of type (Socket) -resource(%d) of type (Socket) -resource(%d) of type (Socket) +object(Socket)#%d (0) { +} +object(Socket)#%d (0) { +} +object(Socket)#%d (0) { +} resource(%d) of type (Unknown) Warning: socket_wsaprotocol_info_export(): Unable to export WSA protocol info [0x00002726]: %s From 90ce7299be0ae2b0ad1bb8b59a90f7da7e317a32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Sun, 2 Aug 2020 11:42:13 +0200 Subject: [PATCH 2/8] Address code review and fix some issues --- UPGRADING | 4 +- .../posix_ttyname_error_wrongparams.phpt | 2 +- ext/sockets/conversions.c | 1 - ext/sockets/sockets.c | 58 ++++++++++++------- ext/sockets/sockets.stub.php | 3 +- ext/sockets/sockets_arginfo.h | 6 +- ext/sockets/tests/bug76839.phpt | 4 +- ext/sockets/tests/ipv4loop.phpt | 6 -- ext/sockets/tests/ipv6loop.phpt | 6 -- .../tests/socket_cmsg_credentials.phpt | 2 +- ext/sockets/tests/socket_cmsg_rights.phpt | 2 +- ext/sockets/tests/socket_connect_params.phpt | 7 +-- ext/sockets/tests/socket_export_stream-1.phpt | 2 +- ext/sockets/tests/socket_export_stream-2.phpt | 16 ++--- ext/sockets/tests/socket_export_stream-4.phpt | 6 +- ext/sockets/tests/socket_import_stream-2.phpt | 6 +- ext/sockets/tests/socket_import_stream-4.phpt | 6 +- .../tests/socket_select-wrongparams-2.phpt | 10 +++- ext/sockets/tests/socket_select_error.phpt | 2 +- .../tests/socket_set_block-retval.phpt | 8 +-- .../tests/socket_set_nonblock-retval.phpt | 8 +-- 21 files changed, 80 insertions(+), 85 deletions(-) diff --git a/UPGRADING b/UPGRADING index f1b34a53877e1..2db3c70b24eb9 100644 --- a/UPGRADING +++ b/UPGRADING @@ -466,9 +466,7 @@ PHP 8.0 UPGRADE NOTES socket_import_stream(), socket_addrinfo_connect(), socket_addrinfo_bind(), and socket_wsaprotocol_info_import() will now return a Socket object rather than a resource. Return value checks using is_resource() should be replaced - with checks for `false`. The socket_close() function is deprecated and no - longer has an effect, instead the Socket instance is automatically - destroyed if it is no longer referenced. + with checks for `false`. . socket_addrinfo_lookup() will now return an array of AddressInfo objects rather than resources. diff --git a/ext/posix/tests/posix_ttyname_error_wrongparams.phpt b/ext/posix/tests/posix_ttyname_error_wrongparams.phpt index 8d10ce5497757..d66651652197c 100644 --- a/ext/posix/tests/posix_ttyname_error_wrongparams.phpt +++ b/ext/posix/tests/posix_ttyname_error_wrongparams.phpt @@ -20,7 +20,7 @@ PHP Testfest Berlin 2009-05-10 getMessage(), "\n"; } diff --git a/ext/sockets/conversions.c b/ext/sockets/conversions.c index 712c1cef53c2f..80bc331a66255 100644 --- a/ext/sockets/conversions.c +++ b/ext/sockets/conversions.c @@ -1409,7 +1409,6 @@ void to_zval_read_fd_array(const char *data, zval *zv, res_context *ctx) return; } if (S_ISSOCK(statbuf.st_mode)) { - object_init_ex(&elem, socket_ce); php_socket *sock = Z_SOCKET_P(&elem); diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index 6b6af26215049..66db692352d64 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -144,10 +144,8 @@ static HashTable *socket_get_gc(zend_object *object, zval **table, int *n) { php_socket *socket = socket_from_obj(object); - zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); - - zend_get_gc_buffer_add_zval(gc_buffer, &socket->zstream); - zend_get_gc_buffer_use(gc_buffer, table, n); + *table = &socket->zstream; + *n = 1; return zend_std_get_properties(object); } @@ -933,11 +931,27 @@ PHP_FUNCTION(socket_listen) /* {{{ Closes a file descriptor */ PHP_FUNCTION(socket_close) { - zval *arg1; + zval *arg1; + php_socket *php_socket; if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &arg1, socket_ce) == FAILURE) { RETURN_THROWS(); } + + php_socket = Z_SOCKET_P(arg1); + + if (!Z_ISUNDEF(php_socket->zstream)) { + php_stream *stream = NULL; + php_stream_from_zval_no_verify(stream, &php_socket->zstream); + if (stream != NULL) { + /* close & destroy stream, incl. removing it from the rsrc list; + * resource stored in php_sock->zstream will become invalid */ + php_stream_free(stream, + PHP_STREAM_FREE_KEEP_RSRC | PHP_STREAM_FREE_CLOSE | + (stream->is_persistent?PHP_STREAM_FREE_CLOSE_PERSISTENT:0)); + } + ZVAL_UNDEF(&php_socket->zstream); + } } /* }}} */ @@ -1236,7 +1250,7 @@ PHP_FUNCTION(socket_connect) int retval; size_t addr_len; zend_long port; - zend_bool port_is_null; + zend_bool port_is_null = 1; if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os|l!", &resource_socket, socket_ce, &addr, &addr_len, &port, &port_is_null) == FAILURE) { RETURN_THROWS(); @@ -1249,8 +1263,8 @@ PHP_FUNCTION(socket_connect) case AF_INET6: { struct sockaddr_in6 sin6 = {0}; - if (port) { - zend_argument_value_error(3, "must be specified for the AF_INET6 socket type"); + if (port_is_null) { + zend_argument_value_error(3, "cannot be null when the socket type is AF_INET6"); RETURN_THROWS(); } @@ -1271,7 +1285,7 @@ PHP_FUNCTION(socket_connect) struct sockaddr_in sin = {0}; if (port_is_null) { - zend_argument_value_error(3, "cannot be null for the AF_INET socket type"); + zend_argument_value_error(3, "cannot be null when the socket type is AF_INET"); RETURN_THROWS(); } @@ -1461,13 +1475,13 @@ PHP_FUNCTION(socket_send) RETURN_THROWS(); } - php_sock = Z_SOCKET_P(arg1); - if (len < 0) { zend_argument_value_error(3, "must be greater than or equal to 0"); RETURN_THROWS(); } + php_sock = Z_SOCKET_P(arg1); + retval = send(php_sock->bsd_socket, buf, (buf_len < (size_t)len ? buf_len : (size_t)len), flags); if (retval == (size_t)-1) { @@ -1606,21 +1620,21 @@ PHP_FUNCTION(socket_sendto) #endif int retval; size_t buf_len, addr_len; - zend_long len, flags, port = 0; + zend_long len, flags, port; + zend_bool port_is_null = 1; char *buf, *addr; - int argc = ZEND_NUM_ARGS(); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oslls|l", &arg1, socket_ce, &buf, &buf_len, &len, &flags, &addr, &addr_len, &port) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oslls|l!", &arg1, socket_ce, &buf, &buf_len, &len, &flags, &addr, &addr_len, &port, &port_is_null) == FAILURE) { RETURN_THROWS(); } - php_sock = Z_SOCKET_P(arg1); - if (len < 0) { zend_argument_value_error(3, "must be greater than or equal to 0"); RETURN_THROWS(); } + php_sock = Z_SOCKET_P(arg1); + switch (php_sock->type) { case AF_UNIX: memset(&s_un, 0, sizeof(s_un)); @@ -1631,8 +1645,9 @@ PHP_FUNCTION(socket_sendto) break; case AF_INET: - if (argc != 6) { - WRONG_PARAM_COUNT; + if (port_is_null) { + zend_argument_value_error(6, "cannot be null when the socket type is AF_INET"); + RETURN_THROWS(); } memset(&sin, 0, sizeof(sin)); @@ -1647,8 +1662,9 @@ PHP_FUNCTION(socket_sendto) break; #if HAVE_IPV6 case AF_INET6: - if (argc != 6) { - WRONG_PARAM_COUNT; + if (port_is_null) { + zend_argument_value_error(6, "cannot be null when the socket type is AF_INET6"); + RETURN_THROWS(); } memset(&sin6, 0, sizeof(sin6)); @@ -2240,7 +2256,7 @@ PHP_FUNCTION(socket_export_stream) PHP_FUNCTION(socket_addrinfo_lookup) { char *service = NULL; - size_t service_len; + size_t service_len = 0; zend_string *hostname, *key; zval *hint, *zhints = NULL; diff --git a/ext/sockets/sockets.stub.php b/ext/sockets/sockets.stub.php index 99dae765ad7b7..b3f0dcbbc216d 100644 --- a/ext/sockets/sockets.stub.php +++ b/ext/sockets/sockets.stub.php @@ -22,7 +22,6 @@ function socket_set_block(Socket $socket): bool {} function socket_listen(Socket $socket, int $backlog = 0): bool {} -/** @deprecated */ function socket_close(Socket $socket): void {} function socket_write(Socket $socket, string $buf, ?int $length = null): int|false {} @@ -60,7 +59,7 @@ function socket_send(Socket $socket, string $buf, int $len, int $flags): int|fal */ function socket_recvfrom(Socket $socket, &$buf, int $len, int $flags, &$name, &$port = UNKNOWN): int|false {} -function socket_sendto(Socket $socket, string $buf, int $len, int $flags, string $addr, int $port = 0): int|false {} +function socket_sendto(Socket $socket, string $buf, int $len, int $flags, string $addr, ?int $port = null): int|false {} function socket_get_option(Socket $socket, int $level, int $optname): array|int|false {} diff --git a/ext/sockets/sockets_arginfo.h b/ext/sockets/sockets_arginfo.h index 855e24094a34a..234b0c7982df0 100644 --- a/ext/sockets/sockets_arginfo.h +++ b/ext/sockets/sockets_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 1b2cbff950087492186cb8c216864b6e51abcf28 */ + * Stub hash: 3256069f3943ec6dac1db915d737324962dda7c4 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_select, 0, 4, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(1, read_fds, IS_ARRAY, 1) @@ -104,7 +104,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_sendto, 0, 5, MAY_BE_LONG ZEND_ARG_TYPE_INFO(0, len, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, flags, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, addr, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, port, IS_LONG, 0, "0") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, port, IS_LONG, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_get_option, 0, 3, MAY_BE_ARRAY|MAY_BE_LONG|MAY_BE_FALSE) @@ -266,7 +266,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(socket_set_nonblock, arginfo_socket_set_nonblock) ZEND_FE(socket_set_block, arginfo_socket_set_block) ZEND_FE(socket_listen, arginfo_socket_listen) - ZEND_DEP_FE(socket_close, arginfo_socket_close) + ZEND_FE(socket_close, arginfo_socket_close) ZEND_FE(socket_write, arginfo_socket_write) ZEND_FE(socket_read, arginfo_socket_read) ZEND_FE(socket_getsockname, arginfo_socket_getsockname) diff --git a/ext/sockets/tests/bug76839.phpt b/ext/sockets/tests/bug76839.phpt index 65d57321c9716..49aff731f70ca 100644 --- a/ext/sockets/tests/bug76839.phpt +++ b/ext/sockets/tests/bug76839.phpt @@ -37,9 +37,9 @@ for ($i = 0; $i < 10; $i++) { socket_sendto($receiverSocket, 'Pong!', 5, 0, $from); echo "Responded to sender with 'Pong!'\n"; - @socket_close($receiverSocket); + socket_close($receiverSocket); unlink($receiverSocketPath); - @socket_close($senderSocket); + socket_close($senderSocket); unlink($senderSocketPath); } --EXPECT-- diff --git a/ext/sockets/tests/ipv4loop.phpt b/ext/sockets/tests/ipv4loop.phpt index 1f3a22b8cb6ef..4e5d15453bc4a 100644 --- a/ext/sockets/tests/ipv4loop.phpt +++ b/ext/sockets/tests/ipv4loop.phpt @@ -51,9 +51,3 @@ IPv4 Loopback test --EXPECT-- string(10) "ABCdef123 " - -Deprecated: Function socket_close() is deprecated - -Deprecated: Function socket_close() is deprecated - -Deprecated: Function socket_close() is deprecated diff --git a/ext/sockets/tests/ipv6loop.phpt b/ext/sockets/tests/ipv6loop.phpt index 3c04f8588321a..109da5bc2db28 100644 --- a/ext/sockets/tests/ipv6loop.phpt +++ b/ext/sockets/tests/ipv6loop.phpt @@ -55,9 +55,3 @@ IPv6 Loopback test --EXPECT-- string(10) "ABCdef123 " - -Deprecated: Function socket_close() is deprecated - -Deprecated: Function socket_close() is deprecated - -Deprecated: Function socket_close() is deprecated diff --git a/ext/sockets/tests/socket_cmsg_credentials.phpt b/ext/sockets/tests/socket_cmsg_credentials.phpt index 50663d733ef72..33f770510f840 100644 --- a/ext/sockets/tests/socket_cmsg_credentials.phpt +++ b/ext/sockets/tests/socket_cmsg_credentials.phpt @@ -67,7 +67,7 @@ bool(true) int(5) Array ( - [name] => + [name] => [control] => Array ( [0] => Array diff --git a/ext/sockets/tests/socket_cmsg_rights.phpt b/ext/sockets/tests/socket_cmsg_rights.phpt index f84bc810635fe..7c7334ffcacc4 100644 --- a/ext/sockets/tests/socket_cmsg_rights.phpt +++ b/ext/sockets/tests/socket_cmsg_rights.phpt @@ -61,7 +61,7 @@ if ($data["control"]) { if ($control["level"] == SOL_SOCKET && $control["type"] == SCM_RIGHTS) { foreach ($control["data"] as $resource) { - if (!is_object($resource)) { + if (!is_resource($resource)) { echo "FAIL RES\n"; var_dump($data); exit; diff --git a/ext/sockets/tests/socket_connect_params.phpt b/ext/sockets/tests/socket_connect_params.phpt index ea7c4971d1fe0..608e5d1c2e517 100644 --- a/ext/sockets/tests/socket_connect_params.phpt +++ b/ext/sockets/tests/socket_connect_params.phpt @@ -17,22 +17,21 @@ socket_getsockname($s_c, $addr, $port); // wrong parameter count try { - $s_w = socket_connect($s_c); + socket_connect($s_c); } catch (\ArgumentCountError $e) { echo $e->getMessage() . \PHP_EOL; } try { - $s_w = socket_connect($s_c, '0.0.0.0'); + socket_connect($s_c, '0.0.0.0'); } catch (\ValueError $e) { echo $e->getMessage() . \PHP_EOL; } $s_w = socket_connect($s_c, '0.0.0.0', $port); socket_close($s_c); - ?> --EXPECTF-- socket_connect() expects at least 2 parameters, 1 given -socket_connect(): Argument #3 ($port) must be specified for the AF_INET socket type +socket_connect(): Argument #3 ($port) cannot be null when the socket type is AF_INET Warning: socket_connect(): unable to connect [%i]: %a in %s on line %d diff --git a/ext/sockets/tests/socket_export_stream-1.phpt b/ext/sockets/tests/socket_export_stream-1.phpt index f8f560b60bd93..d99c79280c675 100644 --- a/ext/sockets/tests/socket_export_stream-1.phpt +++ b/ext/sockets/tests/socket_export_stream-1.phpt @@ -20,7 +20,7 @@ var_dump($stream); socket_write($s1, "test message"); socket_close($s1); -var_dump(stream_get_contents($stream)); +//var_dump(stream_get_contents($stream)); --EXPECTF-- resource(%d) of type (stream) string(12) "test message" diff --git a/ext/sockets/tests/socket_export_stream-2.phpt b/ext/sockets/tests/socket_export_stream-2.phpt index 4e2a632d4601b..7f6ca1c15c605 100644 --- a/ext/sockets/tests/socket_export_stream-2.phpt +++ b/ext/sockets/tests/socket_export_stream-2.phpt @@ -9,31 +9,27 @@ if (!extension_loaded('sockets')) { getMessage(), "\n"; } try { - var_dump(socket_export_stream(stream_socket_server("udp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND))); + socket_export_stream(stream_socket_server("udp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BIND)); } catch (TypeError $e) { echo $e->getMessage(), "\n"; } $s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); var_dump($s); socket_close($s); -try { - var_dump(socket_export_stream($s)); -} catch (TypeError $e) { - echo $e->getMessage(), "\n"; -} +var_dump(socket_export_stream($s)); echo "Done."; ?> --EXPECTF-- -socket_export_stream(): supplied resource is not a valid Socket resource -socket_export_stream(): supplied resource is not a valid Socket resource +socket_export_stream(): Argument #1 ($socket) must be of type Socket, resource given +socket_export_stream(): Argument #1 ($socket) must be of type Socket, resource given object(Socket)#%d (0) { } -socket_export_stream(): supplied resource is not a valid Socket resource +resource(7) of type (stream) Done. diff --git a/ext/sockets/tests/socket_export_stream-4.phpt b/ext/sockets/tests/socket_export_stream-4.phpt index 6acc88d16b8f8..9f88b7ce478c8 100644 --- a/ext/sockets/tests/socket_export_stream-4.phpt +++ b/ext/sockets/tests/socket_export_stream-4.phpt @@ -105,9 +105,11 @@ Warning: socket_get_option(): Unable to retrieve socket option [%d]: %s in %s on close socket stream_set_blocking stream_set_blocking(): supplied resource is not a valid stream resource -socket_set_block socket_set_block(): supplied resource is not a valid Socket resource +socket_set_block +Warning: socket_set_block(): unable to set blocking mode [9]: Bad file descriptor in %s on line %d -socket_get_option socket_get_option(): supplied resource is not a valid Socket resource +socket_get_option +Warning: socket_get_option(): Unable to retrieve socket option [9]: Bad file descriptor in %s on line %d Done. diff --git a/ext/sockets/tests/socket_import_stream-2.phpt b/ext/sockets/tests/socket_import_stream-2.phpt index 37849f67ab496..a16a3dc18a54a 100644 --- a/ext/sockets/tests/socket_import_stream-2.phpt +++ b/ext/sockets/tests/socket_import_stream-2.phpt @@ -10,7 +10,7 @@ if (!extension_loaded('sockets')) { var_dump(socket_import_stream(fopen(__FILE__, "rb"))); try { - var_dump(socket_import_stream(socket_create(AF_INET, SOCK_DGRAM, SOL_UDP))); + socket_import_stream(socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)); } catch (TypeError $e) { echo $e->getMessage(), "\n"; } @@ -18,7 +18,7 @@ $s = stream_socket_server("udp://127.0.0.1:0", $errno, $errstr, STREAM_SERVER_BI var_dump($s); var_dump(fclose($s)); try { - var_dump(socket_import_stream($s)); + socket_import_stream($s); } catch (TypeError $e) { echo $e->getMessage(), "\n"; } @@ -28,7 +28,7 @@ echo "Done."; --EXPECTF-- Warning: socket_import_stream(): Cannot represent a stream of type STDIO as a Socket Descriptor in %s on line %d bool(false) -socket_import_stream(): supplied resource is not a valid stream resource +socket_import_stream(): Argument #1 ($stream) must be of type resource, Socket given resource(%d) of type (stream) bool(true) socket_import_stream(): supplied resource is not a valid stream resource diff --git a/ext/sockets/tests/socket_import_stream-4.phpt b/ext/sockets/tests/socket_import_stream-4.phpt index a4c38b5a1b163..b6ebcee3bce07 100644 --- a/ext/sockets/tests/socket_import_stream-4.phpt +++ b/ext/sockets/tests/socket_import_stream-4.phpt @@ -100,9 +100,11 @@ Warning: socket_get_option(): Unable to retrieve socket option [%d]: %s in %s on close socket stream_set_blocking stream_set_blocking(): supplied resource is not a valid stream resource -socket_set_block socket_set_block(): supplied resource is not a valid Socket resource +socket_set_block +Warning: socket_set_block(): unable to set blocking mode [9]: Bad file descriptor in %s on line %d -socket_get_option socket_get_option(): supplied resource is not a valid Socket resource +socket_get_option +Warning: socket_get_option(): Unable to retrieve socket option [9]: Bad file descriptor in %s on line %d Done. diff --git a/ext/sockets/tests/socket_select-wrongparams-2.phpt b/ext/sockets/tests/socket_select-wrongparams-2.phpt index d45bc4c44a717..601ddb4efa343 100644 --- a/ext/sockets/tests/socket_select-wrongparams-2.phpt +++ b/ext/sockets/tests/socket_select-wrongparams-2.phpt @@ -11,10 +11,14 @@ $sockets = null; $write = null; $except = null; $time = 0; -var_dump(socket_select($sockets, $write, $except, $time)); + +try { + socket_select($sockets, $write, $except, $time); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} --EXPECTF-- -Warning: socket_select(): No resource arrays were passed to select in %s on line %d -bool(false) +socket_select(): At least one array argument must be passed --CREDITS-- Till Klampaeckel, till@php.net Berlin TestFest 2009 diff --git a/ext/sockets/tests/socket_select_error.phpt b/ext/sockets/tests/socket_select_error.phpt index 48acb330200eb..645707467dc1c 100644 --- a/ext/sockets/tests/socket_select_error.phpt +++ b/ext/sockets/tests/socket_select_error.phpt @@ -14,4 +14,4 @@ try { } ?> --EXPECT-- -socket_select(): supplied argument is not a valid Socket resource +socket_select(): Argument #1 ($read_fds) must only have elements of type Socket, string given diff --git a/ext/sockets/tests/socket_set_block-retval.phpt b/ext/sockets/tests/socket_set_block-retval.phpt index 89dcc7ab4f47a..313a525080825 100644 --- a/ext/sockets/tests/socket_set_block-retval.phpt +++ b/ext/sockets/tests/socket_set_block-retval.phpt @@ -15,16 +15,12 @@ socket_close($socket); $socket2 = socket_create_listen(31340); socket_close($socket2); -try { - var_dump(socket_set_block($socket2)); -} catch (TypeError $e) { - echo $e->getMessage(), "\n"; -} +var_dump(socket_set_block($socket2)); ?> --EXPECT-- bool(true) -socket_set_block(): supplied resource is not a valid Socket resource +bool(true) --CREDITS-- Robin Mehner, robin@coding-robin.de PHP Testfest Berlin 2009-05-09 diff --git a/ext/sockets/tests/socket_set_nonblock-retval.phpt b/ext/sockets/tests/socket_set_nonblock-retval.phpt index fb0e593810b54..222c87632e6a9 100644 --- a/ext/sockets/tests/socket_set_nonblock-retval.phpt +++ b/ext/sockets/tests/socket_set_nonblock-retval.phpt @@ -15,16 +15,12 @@ socket_close($socket); $socket2 = socket_create_listen(31340); socket_close($socket2); -try { - var_dump(socket_set_nonblock($socket2)); -} catch (TypeError $e) { - echo $e->getMessage(), "\n"; -} +var_dump(socket_set_nonblock($socket2)); ?> --EXPECT-- bool(true) -socket_set_nonblock(): supplied resource is not a valid Socket resource +bool(true) --CREDITS-- Robin Mehner, robin@coding-robin.de PHP Testfest Berlin 2009-05-09 From 8fd1305d7fa85048de4f392e8de4a6dc2e455e20 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 3 Aug 2020 12:30:05 +0200 Subject: [PATCH 3/8] Fix socket_ce declaration --- ext/sockets/php_sockets.h | 2 +- ext/sockets/sockets.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/sockets/php_sockets.h b/ext/sockets/php_sockets.h index d8008b07cfa88..0115b9263fba2 100644 --- a/ext/sockets/php_sockets.h +++ b/ext/sockets/php_sockets.h @@ -63,7 +63,7 @@ typedef struct { zend_object std; } php_socket; -zend_class_entry *socket_ce; +extern zend_class_entry *socket_ce; static inline php_socket *socket_from_obj(zend_object *obj) { return (php_socket *)((char *)(obj) - XtOffsetOf(php_socket, std)); diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index 66db692352d64..d6af377427d62 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -102,6 +102,7 @@ static PHP_RSHUTDOWN_FUNCTION(sockets); /* Socket class */ +zend_class_entry *socket_ce; static zend_object_handlers socket_object_handlers; static zend_object *socket_create_object(zend_class_entry *class_type) { From 5c5d687b8815da83c4149ae30d16482f67377ed0 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 3 Aug 2020 12:37:14 +0200 Subject: [PATCH 4/8] Fix addrinfo segfault --- ext/sockets/sockets.c | 6 +++++- ext/sockets/tests/socket_addrinfo_bind.phpt | 2 +- ext/sockets/tests/socket_addrinfo_connect.phpt | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index d6af377427d62..65d3bf3977e01 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -186,10 +186,11 @@ static void address_info_free_obj(zend_object *object) { php_addrinfo *address_info = address_info_from_obj(object); - efree(address_info->addrinfo->ai_addr); if (address_info->addrinfo->ai_canonname != NULL) { efree(address_info->addrinfo->ai_canonname); } + efree(address_info->addrinfo->ai_addr); + efree(address_info->addrinfo); zend_object_std_dtor(&address_info->std); } @@ -2302,6 +2303,9 @@ PHP_FUNCTION(socket_addrinfo_lookup) object_init_ex(&zaddr, address_info_ce); res = Z_ADDRESS_INFO_P(&zaddr); + res->addrinfo = emalloc(sizeof(struct addrinfo)); + memcpy(res->addrinfo, rp, sizeof(struct addrinfo)); + res->addrinfo->ai_addr = emalloc(rp->ai_addrlen); memcpy(res->addrinfo->ai_addr, rp->ai_addr, rp->ai_addrlen); diff --git a/ext/sockets/tests/socket_addrinfo_bind.phpt b/ext/sockets/tests/socket_addrinfo_bind.phpt index 59259728689c2..40a746bdb932f 100644 --- a/ext/sockets/tests/socket_addrinfo_bind.phpt +++ b/ext/sockets/tests/socket_addrinfo_bind.phpt @@ -14,6 +14,6 @@ $addrinfo = socket_addrinfo_lookup('127.0.0.1', 2000, array( var_dump(socket_addrinfo_bind($addrinfo[0])); echo "Done"; --EXPECT-- -object(Socket)#1 (0) { +object(Socket)#2 (0) { } Done diff --git a/ext/sockets/tests/socket_addrinfo_connect.phpt b/ext/sockets/tests/socket_addrinfo_connect.phpt index f162449b9a4a8..a5a604ee61d9e 100644 --- a/ext/sockets/tests/socket_addrinfo_connect.phpt +++ b/ext/sockets/tests/socket_addrinfo_connect.phpt @@ -14,6 +14,6 @@ $addrinfo = socket_addrinfo_lookup('127.0.0.1', 2000, array( var_dump(socket_addrinfo_connect($addrinfo[0])); echo "Done"; --EXPECT-- -object(Socket)#1 (0) { +object(Socket)#2 (0) { } Done From fae00abd41ebc8c23a6f5c0344069c206e46f69c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 3 Aug 2020 12:39:47 +0200 Subject: [PATCH 5/8] Suppress leaks in tests These seem to be intentionally testing memory leaks??? --- ext/sockets/tests/socket_export_stream-5.phpt | 3 +++ ext/sockets/tests/socket_import_stream-5.phpt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/ext/sockets/tests/socket_export_stream-5.phpt b/ext/sockets/tests/socket_export_stream-5.phpt index 5a1d03fa6e072..219fec5574cdc 100644 --- a/ext/sockets/tests/socket_export_stream-5.phpt +++ b/ext/sockets/tests/socket_export_stream-5.phpt @@ -7,6 +7,9 @@ if (!extension_loaded('sockets')) { } if (!function_exists('zend_leak_variable')) die('SKIP only for debug builds'); +?> +--INI-- +report_memleaks=0 --FILE-- +--INI-- +report_memleaks=0 --FILE-- Date: Mon, 3 Aug 2020 18:57:01 +0200 Subject: [PATCH 6/8] Remove unnecessary indirection in addrinfo struct --- ext/sockets/sockets.c | 52 +++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index 65d3bf3977e01..c574b4215a3a9 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -154,7 +154,7 @@ static HashTable *socket_get_gc(zend_object *object, zval **table, int *n) /* AddressInfo class */ typedef struct { - struct addrinfo *addrinfo; + struct addrinfo addrinfo; zend_object std; } php_addrinfo; @@ -186,11 +186,10 @@ static void address_info_free_obj(zend_object *object) { php_addrinfo *address_info = address_info_from_obj(object); - if (address_info->addrinfo->ai_canonname != NULL) { - efree(address_info->addrinfo->ai_canonname); + if (address_info->addrinfo.ai_canonname != NULL) { + efree(address_info->addrinfo.ai_canonname); } - efree(address_info->addrinfo->ai_addr); - efree(address_info->addrinfo); + efree(address_info->addrinfo.ai_addr); zend_object_std_dtor(&address_info->std); } @@ -2303,14 +2302,13 @@ PHP_FUNCTION(socket_addrinfo_lookup) object_init_ex(&zaddr, address_info_ce); res = Z_ADDRESS_INFO_P(&zaddr); - res->addrinfo = emalloc(sizeof(struct addrinfo)); - memcpy(res->addrinfo, rp, sizeof(struct addrinfo)); + memcpy(&res->addrinfo, rp, sizeof(struct addrinfo)); - res->addrinfo->ai_addr = emalloc(rp->ai_addrlen); - memcpy(res->addrinfo->ai_addr, rp->ai_addr, rp->ai_addrlen); + res->addrinfo.ai_addr = emalloc(rp->ai_addrlen); + memcpy(res->addrinfo.ai_addr, rp->ai_addr, rp->ai_addrlen); if (rp->ai_canonname != NULL) { - res->addrinfo->ai_canonname = estrdup(rp->ai_canonname); + res->addrinfo.ai_canonname = estrdup(rp->ai_canonname); } add_next_index_zval(return_value, &zaddr); @@ -2338,8 +2336,8 @@ PHP_FUNCTION(socket_addrinfo_bind) object_init_ex(return_value, socket_ce); php_sock = Z_SOCKET_P(return_value); - php_sock->bsd_socket = socket(ai->addrinfo->ai_family, ai->addrinfo->ai_socktype, ai->addrinfo->ai_protocol); - php_sock->type = ai->addrinfo->ai_family; + php_sock->bsd_socket = socket(ai->addrinfo.ai_family, ai->addrinfo.ai_socktype, ai->addrinfo.ai_protocol); + php_sock->type = ai->addrinfo.ai_family; if (IS_INVALID_SOCKET(php_sock)) { SOCKETS_G(last_error) = errno; @@ -2365,7 +2363,7 @@ PHP_FUNCTION(socket_addrinfo_bind) case AF_INET6: #endif { - retval = bind(php_sock->bsd_socket, ai->addrinfo->ai_addr, ai->addrinfo->ai_addrlen); + retval = bind(php_sock->bsd_socket, ai->addrinfo.ai_addr, ai->addrinfo.ai_addrlen); break; } default: @@ -2401,8 +2399,8 @@ PHP_FUNCTION(socket_addrinfo_connect) object_init_ex(return_value, socket_ce); php_sock = Z_SOCKET_P(return_value); - php_sock->bsd_socket = socket(ai->addrinfo->ai_family, ai->addrinfo->ai_socktype, ai->addrinfo->ai_protocol); - php_sock->type = ai->addrinfo->ai_family; + php_sock->bsd_socket = socket(ai->addrinfo.ai_family, ai->addrinfo.ai_socktype, ai->addrinfo.ai_protocol); + php_sock->type = ai->addrinfo.ai_family; if (IS_INVALID_SOCKET(php_sock)) { SOCKETS_G(last_error) = errno; @@ -2428,7 +2426,7 @@ PHP_FUNCTION(socket_addrinfo_connect) case AF_INET6: #endif { - retval = connect(php_sock->bsd_socket, ai->addrinfo->ai_addr, ai->addrinfo->ai_addrlen); + retval = connect(php_sock->bsd_socket, ai->addrinfo.ai_addr, ai->addrinfo.ai_addrlen); break; } default: @@ -2461,34 +2459,34 @@ PHP_FUNCTION(socket_addrinfo_explain) array_init(return_value); - add_assoc_long(return_value, "ai_flags", ai->addrinfo->ai_flags); - add_assoc_long(return_value, "ai_family", ai->addrinfo->ai_family); - add_assoc_long(return_value, "ai_socktype", ai->addrinfo->ai_socktype); - add_assoc_long(return_value, "ai_protocol", ai->addrinfo->ai_protocol); - if (ai->addrinfo->ai_canonname != NULL) { - add_assoc_string(return_value, "ai_canonname", ai->addrinfo->ai_canonname); + add_assoc_long(return_value, "ai_flags", ai->addrinfo.ai_flags); + add_assoc_long(return_value, "ai_family", ai->addrinfo.ai_family); + add_assoc_long(return_value, "ai_socktype", ai->addrinfo.ai_socktype); + add_assoc_long(return_value, "ai_protocol", ai->addrinfo.ai_protocol); + if (ai->addrinfo.ai_canonname != NULL) { + add_assoc_string(return_value, "ai_canonname", ai->addrinfo.ai_canonname); } array_init(&sockaddr); - switch(ai->addrinfo->ai_family) { + switch (ai->addrinfo.ai_family) { case AF_INET: { - struct sockaddr_in *sa = (struct sockaddr_in *) ai->addrinfo->ai_addr; + struct sockaddr_in *sa = (struct sockaddr_in *) ai->addrinfo.ai_addr; char addr[INET_ADDRSTRLEN]; add_assoc_long(&sockaddr, "sin_port", ntohs((unsigned short) sa->sin_port)); - inet_ntop(ai->addrinfo->ai_family, &sa->sin_addr, addr, sizeof(addr)); + inet_ntop(ai->addrinfo.ai_family, &sa->sin_addr, addr, sizeof(addr)); add_assoc_string(&sockaddr, "sin_addr", addr); break; } #if HAVE_IPV6 case AF_INET6: { - struct sockaddr_in6 *sa = (struct sockaddr_in6 *) ai->addrinfo->ai_addr; + struct sockaddr_in6 *sa = (struct sockaddr_in6 *) ai->addrinfo.ai_addr; char addr[INET6_ADDRSTRLEN]; add_assoc_long(&sockaddr, "sin6_port", ntohs((unsigned short) sa->sin6_port)); - inet_ntop(ai->addrinfo->ai_family, &sa->sin6_addr, addr, sizeof(addr)); + inet_ntop(ai->addrinfo.ai_family, &sa->sin6_addr, addr, sizeof(addr)); add_assoc_string(&sockaddr, "sin6_addr", addr); break; } From 6f1b8cab0f07e3afdcf52e31fbd1a5eaab08c1f5 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 3 Aug 2020 19:07:39 +0200 Subject: [PATCH 7/8] Fix socket closing --- ext/sockets/sockets.c | 8 +++++++- ext/sockets/tests/socket_export_stream-1.phpt | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index c574b4215a3a9..2c9b19dc27504 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -951,8 +951,14 @@ PHP_FUNCTION(socket_close) PHP_STREAM_FREE_KEEP_RSRC | PHP_STREAM_FREE_CLOSE | (stream->is_persistent?PHP_STREAM_FREE_CLOSE_PERSISTENT:0)); } - ZVAL_UNDEF(&php_socket->zstream); + } else { + if (!IS_INVALID_SOCKET(php_socket)) { + close(php_socket->bsd_socket); + } } + + ZVAL_UNDEF(&php_socket->zstream); + php_socket->bsd_socket = -1; } /* }}} */ diff --git a/ext/sockets/tests/socket_export_stream-1.phpt b/ext/sockets/tests/socket_export_stream-1.phpt index d99c79280c675..f8f560b60bd93 100644 --- a/ext/sockets/tests/socket_export_stream-1.phpt +++ b/ext/sockets/tests/socket_export_stream-1.phpt @@ -20,7 +20,7 @@ var_dump($stream); socket_write($s1, "test message"); socket_close($s1); -//var_dump(stream_get_contents($stream)); +var_dump(stream_get_contents($stream)); --EXPECTF-- resource(%d) of type (stream) string(12) "test message" From a0f43d909f8f63946732eb652b1e5c2b219f9017 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 3 Aug 2020 23:10:35 +0200 Subject: [PATCH 8/8] Check for closed sockets --- ext/sockets/conversions.c | 10 ++++- ext/sockets/php_sockets.h | 8 ++++ ext/sockets/sendrecvmsg.c | 2 + ext/sockets/sockets.c | 38 ++++++++++++++++--- ext/sockets/tests/socket_export_stream-2.phpt | 8 +++- ext/sockets/tests/socket_export_stream-4.phpt | 22 +++++------ ext/sockets/tests/socket_import_stream-4.phpt | 22 +++++------ .../tests/socket_set_block-retval.phpt | 11 +++--- .../tests/socket_set_nonblock-retval.phpt | 11 +++--- 9 files changed, 89 insertions(+), 43 deletions(-) diff --git a/ext/sockets/conversions.c b/ext/sockets/conversions.c index 80bc331a66255..ea460662e1f4a 100644 --- a/ext/sockets/conversions.c +++ b/ext/sockets/conversions.c @@ -1341,10 +1341,16 @@ static void from_zval_write_fd_array_aux(zval *elem, unsigned i, void **args, se if (Z_TYPE_P(elem) == IS_OBJECT && Z_OBJCE_P(elem) == socket_ce) { php_socket *sock = Z_SOCKET_P(elem); - iarr[i] = sock->bsd_socket; + if (IS_INVALID_SOCKET(sock)) { + do_from_zval_err(ctx, "socket is already closed"); + return; + } + iarr[i] = sock->bsd_socket; return; - } else if (Z_TYPE_P(elem) == IS_RESOURCE) { + } + + if (Z_TYPE_P(elem) == IS_RESOURCE) { php_stream *stream; stream = (php_stream *)zend_fetch_resource2_ex(elem, NULL, php_file_le_stream(), php_file_le_pstream()); diff --git a/ext/sockets/php_sockets.h b/ext/sockets/php_sockets.h index 0115b9263fba2..83d5bdd7c25d8 100644 --- a/ext/sockets/php_sockets.h +++ b/ext/sockets/php_sockets.h @@ -29,6 +29,8 @@ #include #ifdef PHP_WIN32 # include "windows_common.h" +#else +# define IS_INVALID_SOCKET(a) (a->bsd_socket < 0) #endif #define PHP_SOCKETS_VERSION PHP_VERSION @@ -71,6 +73,12 @@ static inline php_socket *socket_from_obj(zend_object *obj) { #define Z_SOCKET_P(zv) socket_from_obj(Z_OBJ_P(zv)) +#define ENSURE_SOCKET_VALID(php_sock) do { \ + if (IS_INVALID_SOCKET(php_sock)) { \ + zend_argument_error(NULL, 1, "has already been closed"); \ + RETURN_THROWS(); \ + } \ +} while (0) #ifdef PHP_WIN32 struct sockaddr_un { diff --git a/ext/sockets/sendrecvmsg.c b/ext/sockets/sendrecvmsg.c index c7194e7798f35..97602f066863f 100644 --- a/ext/sockets/sendrecvmsg.c +++ b/ext/sockets/sendrecvmsg.c @@ -179,6 +179,7 @@ PHP_FUNCTION(socket_sendmsg) LONG_CHECK_VALID_INT(flags, 3); php_sock = Z_SOCKET_P(zsocket); + ENSURE_SOCKET_VALID(php_sock); msghdr = from_zval_run_conversions(zmsg, php_sock, from_zval_write_msghdr_send, sizeof(*msghdr), "msghdr", &allocations, &err); @@ -220,6 +221,7 @@ PHP_FUNCTION(socket_recvmsg) LONG_CHECK_VALID_INT(flags, 3); php_sock = Z_SOCKET_P(zsocket); + ENSURE_SOCKET_VALID(php_sock); msghdr = from_zval_run_conversions(zmsg, php_sock, from_zval_write_msghdr_recv, sizeof(*msghdr), "msghdr", &allocations, &err); diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index 2c9b19dc27504..e1f7ec392c743 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -51,7 +51,6 @@ # include # include # include -# define IS_INVALID_SOCKET(a) (a->bsd_socket < 0) # define set_errno(a) (errno = a) # include "php_sockets.h" # if HAVE_IF_NAMETOINDEX @@ -659,6 +658,10 @@ static int php_sock_array_to_fd_set(uint32_t arg_num, zval *sock_array, fd_set * } php_sock = Z_SOCKET_P(element); + if (IS_INVALID_SOCKET(php_sock)) { + zend_argument_type_error(arg_num, "contains a closed socket"); + return -1; + } PHP_SAFE_FD_SET(php_sock->bsd_socket, fds); if (php_sock->bsd_socket > *max_fd) { @@ -689,6 +692,7 @@ static int php_sock_array_from_fd_set(zval *sock_array, fd_set *fds) /* {{{ */ php_sock = Z_SOCKET_P(element); ZEND_ASSERT(php_sock); /* element is supposed to be Socket object */ + ZEND_ASSERT(!IS_INVALID_SOCKET(php_sock)); if (PHP_SAFE_FD_ISSET(php_sock->bsd_socket, fds)) { /* Add fd to new array */ @@ -825,6 +829,7 @@ PHP_FUNCTION(socket_accept) } php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); object_init_ex(return_value, socket_ce); new_sock = Z_SOCKET_P(return_value); @@ -847,6 +852,7 @@ PHP_FUNCTION(socket_set_nonblock) } php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); if (!Z_ISUNDEF(php_sock->zstream)) { php_stream *stream; @@ -882,6 +888,7 @@ PHP_FUNCTION(socket_set_block) } php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); /* if socket was created from a stream, give the stream a chance to take * care of the operation itself, thereby allowing it to update its internal @@ -920,6 +927,7 @@ PHP_FUNCTION(socket_listen) } php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); if (listen(php_sock->bsd_socket, backlog) != 0) { PHP_SOCKET_ERROR(php_sock, "unable to listen on socket", errno); @@ -940,6 +948,7 @@ PHP_FUNCTION(socket_close) } php_socket = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_socket); if (!Z_ISUNDEF(php_socket->zstream)) { php_stream *stream = NULL; @@ -978,6 +987,7 @@ PHP_FUNCTION(socket_write) } php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); if (length < 0) { zend_argument_value_error(3, "must be greater than or equal to 0"); @@ -1017,6 +1027,7 @@ PHP_FUNCTION(socket_read) } php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); /* overflow check */ if ((length + 1) < 2) { @@ -1081,6 +1092,7 @@ PHP_FUNCTION(socket_getsockname) } php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); sa = (struct sockaddr *) &sa_storage; @@ -1152,6 +1164,7 @@ PHP_FUNCTION(socket_getpeername) } php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); sa = (struct sockaddr *) &sa_storage; @@ -1264,6 +1277,7 @@ PHP_FUNCTION(socket_connect) } php_sock = Z_SOCKET_P(resource_socket); + ENSURE_SOCKET_VALID(php_sock); switch(php_sock->type) { #if HAVE_IPV6 @@ -1366,6 +1380,7 @@ PHP_FUNCTION(socket_bind) } php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); switch(php_sock->type) { case AF_UNIX: @@ -1443,6 +1458,7 @@ PHP_FUNCTION(socket_recv) } php_sock = Z_SOCKET_P(php_sock_res); + ENSURE_SOCKET_VALID(php_sock); /* overflow check */ if ((len + 1) < 2) { @@ -1482,13 +1498,14 @@ PHP_FUNCTION(socket_send) RETURN_THROWS(); } + php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); + if (len < 0) { zend_argument_value_error(3, "must be greater than or equal to 0"); RETURN_THROWS(); } - php_sock = Z_SOCKET_P(arg1); - retval = send(php_sock->bsd_socket, buf, (buf_len < (size_t)len ? buf_len : (size_t)len), flags); if (retval == (size_t)-1) { @@ -1522,6 +1539,7 @@ PHP_FUNCTION(socket_recvfrom) } php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); /* overflow check */ /* Shouldthrow ? */ @@ -1635,13 +1653,14 @@ PHP_FUNCTION(socket_sendto) RETURN_THROWS(); } + php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); + if (len < 0) { zend_argument_value_error(3, "must be greater than or equal to 0"); RETURN_THROWS(); } - php_sock = Z_SOCKET_P(arg1); - switch (php_sock->type) { case AF_UNIX: memset(&s_un, 0, sizeof(s_un)); @@ -1718,6 +1737,7 @@ PHP_FUNCTION(socket_get_option) } php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); if (level == IPPROTO_IP) { switch (optname) { @@ -1830,6 +1850,7 @@ PHP_FUNCTION(socket_set_option) } php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); set_errno(0); @@ -2027,6 +2048,7 @@ PHP_FUNCTION(socket_shutdown) } php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); if (shutdown(php_sock->bsd_socket, how_shutdown) != 0) { PHP_SOCKET_ERROR(php_sock, "Unable to shutdown socket", errno); @@ -2050,6 +2072,8 @@ PHP_FUNCTION(socket_last_error) if (arg1) { php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); + RETVAL_LONG(php_sock->error); } else { RETVAL_LONG(SOCKETS_G(last_error)); @@ -2069,6 +2093,8 @@ PHP_FUNCTION(socket_clear_error) if (arg1) { php_sock = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(php_sock); + php_sock->error = 0; } else { SOCKETS_G(last_error) = 0; @@ -2179,6 +2205,7 @@ PHP_FUNCTION(socket_export_stream) } socket = Z_SOCKET_P(zsocket); + ENSURE_SOCKET_VALID(socket); /* Either we already exported a stream or the socket came from an import, * just return the existing stream */ @@ -2520,6 +2547,7 @@ PHP_FUNCTION(socket_wsaprotocol_info_export) } socket = Z_SOCKET_P(arg1); + ENSURE_SOCKET_VALID(socket); if (SOCKET_ERROR == WSADuplicateSocket(socket->bsd_socket, (DWORD)target_pid, &wi)) { DWORD err = WSAGetLastError(); diff --git a/ext/sockets/tests/socket_export_stream-2.phpt b/ext/sockets/tests/socket_export_stream-2.phpt index 7f6ca1c15c605..503db5b00404e 100644 --- a/ext/sockets/tests/socket_export_stream-2.phpt +++ b/ext/sockets/tests/socket_export_stream-2.phpt @@ -22,7 +22,11 @@ $s = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); var_dump($s); socket_close($s); -var_dump(socket_export_stream($s)); +try { + var_dump(socket_export_stream($s)); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} echo "Done."; ?> @@ -31,5 +35,5 @@ socket_export_stream(): Argument #1 ($socket) must be of type Socket, resource g socket_export_stream(): Argument #1 ($socket) must be of type Socket, resource given object(Socket)#%d (0) { } -resource(7) of type (stream) +socket_export_stream(): Argument #1 ($socket) has already been closed Done. diff --git a/ext/sockets/tests/socket_export_stream-4.phpt b/ext/sockets/tests/socket_export_stream-4.phpt index 9f88b7ce478c8..7a38ba91294af 100644 --- a/ext/sockets/tests/socket_export_stream-4.phpt +++ b/ext/sockets/tests/socket_export_stream-4.phpt @@ -16,8 +16,8 @@ function test($stream, $sock) { echo "stream_set_blocking "; try { print_r(stream_set_blocking($stream, 0)); - } catch (TypeError $e) { - echo $e->getMessage(), "\n"; + } catch (Error $e) { + echo get_class($e), ": ", $e->getMessage(), "\n"; } echo "\n"; } @@ -25,15 +25,15 @@ function test($stream, $sock) { echo "socket_set_block "; try { print_r(socket_set_block($sock)); - } catch (TypeError $e) { - echo $e->getMessage(), "\n"; + } catch (Error $e) { + echo get_class($e), ": ", $e->getMessage(), "\n"; } echo "\n"; echo "socket_get_option "; try { print_r(socket_get_option($sock, SOL_SOCKET, SO_TYPE)); - } catch (TypeError $e) { - echo $e->getMessage(), "\n"; + } catch (Error $e) { + echo get_class($e), ": ", $e->getMessage(), "\n"; } echo "\n"; } @@ -92,7 +92,7 @@ stream_set_blocking 1 close stream -stream_set_blocking stream_set_blocking(): supplied resource is not a valid stream resource +stream_set_blocking TypeError: stream_set_blocking(): supplied resource is not a valid stream resource socket_set_block Warning: socket_set_block(): unable to set blocking mode [%d]: %s in %s on line %d @@ -103,13 +103,11 @@ Warning: socket_get_option(): Unable to retrieve socket option [%d]: %s in %s on close socket -stream_set_blocking stream_set_blocking(): supplied resource is not a valid stream resource +stream_set_blocking TypeError: stream_set_blocking(): supplied resource is not a valid stream resource -socket_set_block -Warning: socket_set_block(): unable to set blocking mode [9]: Bad file descriptor in %s on line %d +socket_set_block Error: socket_set_block(): Argument #1 ($socket) has already been closed -socket_get_option -Warning: socket_get_option(): Unable to retrieve socket option [9]: Bad file descriptor in %s on line %d +socket_get_option Error: socket_get_option(): Argument #1 ($socket) has already been closed Done. diff --git a/ext/sockets/tests/socket_import_stream-4.phpt b/ext/sockets/tests/socket_import_stream-4.phpt index b6ebcee3bce07..bd2ac05aefefb 100644 --- a/ext/sockets/tests/socket_import_stream-4.phpt +++ b/ext/sockets/tests/socket_import_stream-4.phpt @@ -16,8 +16,8 @@ function test($stream, $sock) { echo "stream_set_blocking "; try { print_r(stream_set_blocking($stream, 0)); - } catch (TypeError $e) { - echo $e->getMessage(), "\n"; + } catch (Error $e) { + echo get_class($e), ": ", $e->getMessage(), "\n"; } echo "\n"; } @@ -25,15 +25,15 @@ function test($stream, $sock) { echo "socket_set_block "; try { print_r(socket_set_block($sock)); - } catch (TypeError $e) { - echo $e->getMessage(), "\n"; + } catch (Error $e) { + echo get_class($e), ": ", $e->getMessage(), "\n"; } echo "\n"; echo "socket_get_option "; try { print_r(socket_get_option($sock, SOL_SOCKET, SO_TYPE)); - } catch (TypeError $e) { - echo $e->getMessage(), "\n"; + } catch (Error $e) { + echo get_class($e), ": ", $e->getMessage(), "\n"; } echo "\n"; } @@ -87,7 +87,7 @@ stream_set_blocking 1 close stream -stream_set_blocking stream_set_blocking(): supplied resource is not a valid stream resource +stream_set_blocking TypeError: stream_set_blocking(): supplied resource is not a valid stream resource socket_set_block Warning: socket_set_block(): unable to set blocking mode [%d]: %s in %s on line %d @@ -98,13 +98,11 @@ Warning: socket_get_option(): Unable to retrieve socket option [%d]: %s in %s on close socket -stream_set_blocking stream_set_blocking(): supplied resource is not a valid stream resource +stream_set_blocking TypeError: stream_set_blocking(): supplied resource is not a valid stream resource -socket_set_block -Warning: socket_set_block(): unable to set blocking mode [9]: Bad file descriptor in %s on line %d +socket_set_block Error: socket_set_block(): Argument #1 ($socket) has already been closed -socket_get_option -Warning: socket_get_option(): Unable to retrieve socket option [9]: Bad file descriptor in %s on line %d +socket_get_option Error: socket_get_option(): Argument #1 ($socket) has already been closed Done. diff --git a/ext/sockets/tests/socket_set_block-retval.phpt b/ext/sockets/tests/socket_set_block-retval.phpt index 313a525080825..00ec7038de501 100644 --- a/ext/sockets/tests/socket_set_block-retval.phpt +++ b/ext/sockets/tests/socket_set_block-retval.phpt @@ -15,12 +15,13 @@ socket_close($socket); $socket2 = socket_create_listen(31340); socket_close($socket2); -var_dump(socket_set_block($socket2)); +try { + var_dump(socket_set_block($socket2)); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} ?> --EXPECT-- bool(true) -bool(true) ---CREDITS-- -Robin Mehner, robin@coding-robin.de -PHP Testfest Berlin 2009-05-09 +socket_set_block(): Argument #1 ($socket) has already been closed diff --git a/ext/sockets/tests/socket_set_nonblock-retval.phpt b/ext/sockets/tests/socket_set_nonblock-retval.phpt index 222c87632e6a9..6df652132453d 100644 --- a/ext/sockets/tests/socket_set_nonblock-retval.phpt +++ b/ext/sockets/tests/socket_set_nonblock-retval.phpt @@ -15,12 +15,13 @@ socket_close($socket); $socket2 = socket_create_listen(31340); socket_close($socket2); -var_dump(socket_set_nonblock($socket2)); +try { + var_dump(socket_set_nonblock($socket2)); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} ?> --EXPECT-- bool(true) -bool(true) ---CREDITS-- -Robin Mehner, robin@coding-robin.de -PHP Testfest Berlin 2009-05-09 +socket_set_nonblock(): Argument #1 ($socket) has already been closed