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