summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGustavo Lopes <glopes@nebm.ist.utl.pt>2013-07-16 00:03:00 +0200
committerGustavo Lopes <glopes@nebm.ist.utl.pt>2013-07-16 00:03:00 +0200
commit2443df37fd1e4999091881d3ad12c6e7e03dbfab (patch)
tree1e10d715aed595e233d64444062a58e5aaca19a3
parentfb91fc6e2c6a8c6f96aa71f968efe9f712d9cc82 (diff)
parentceecfaff5ac793d50426ae051fd4bec932d23bb1 (diff)
downloadphp-git-2443df37fd1e4999091881d3ad12c6e7e03dbfab.tar.gz
Merge branch 'PHP-5.5'
* PHP-5.5: NEWS for 710150c and e2744f1 socket: support unix paths in the abstract namespace socket: fix bug #65260 (SCM_RIGHTS)
-rw-r--r--ext/sockets/conversions.c37
-rw-r--r--ext/sockets/sockets.c21
-rw-r--r--ext/sockets/tests/socket_abstract_path.phpt44
-rw-r--r--ext/sockets/tests/socket_abstract_path_sendmsg.phpt40
-rw-r--r--ext/sockets/tests/socket_cmsg_rights.phpt1
5 files changed, 130 insertions, 13 deletions
diff --git a/ext/sockets/conversions.c b/ext/sockets/conversions.c
index ea1c95201f..ed55ed52fa 100644
--- a/ext/sockets/conversions.c
+++ b/ext/sockets/conversions.c
@@ -98,8 +98,8 @@ typedef struct {
} field_descriptor;
#define KEY_FILL_SOCKADDR "fill_sockaddr"
-#define KEY_RECVMSG_RET "recvmsg_ret"
-#define KEY_CMSG_LEN "cmsg_len"
+#define KEY_RECVMSG_RET "recvmsg_ret"
+#define KEY_CMSG_LEN "cmsg_len"
const struct key_value empty_key_value_list[] = {{0}};
@@ -223,6 +223,7 @@ static unsigned from_array_iterate(const zval *arr,
char buf[sizeof("element #4294967295")];
char *bufp = buf;
+ /* Note i starts at 1, not 0! */
for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos), i = 1;
!ctx->err.has_error
&& zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&elem, &pos) == SUCCESS;
@@ -666,6 +667,13 @@ static void from_zval_write_sun_path(const zval *path, char *sockaddr_un_c, ser_
path = &lzval;
}
+ /* code in this file relies on the path being nul terminated, even though
+ * this is not required, at least on linux for abstract paths. It also
+ * assumes that the path is not empty */
+ if (Z_STRLEN_P(path) == 0) {
+ do_from_zval_err(ctx, "%s", "the path is cannot be empty");
+ return;
+ }
if (Z_STRLEN_P(path) >= sizeof(saddr->sun_path)) {
do_from_zval_err(ctx, "the path is too long, the maximum permitted "
"length is %ld", sizeof(saddr->sun_path) - 1);
@@ -767,10 +775,22 @@ static void from_zval_write_sockaddr_aux(const zval *container,
return;
}
*sockaddr_ptr = accounted_ecalloc(1, sizeof(struct sockaddr_un), ctx);
- *sockaddr_len = sizeof(struct sockaddr_un);
if (fill_sockaddr) {
+ struct sockaddr_un *sock_un = (struct sockaddr_un*)*sockaddr_ptr;
+
from_zval_write_sockaddr_un(container, (char*)*sockaddr_ptr, ctx);
(*sockaddr_ptr)->sa_family = AF_UNIX;
+
+ /* calculating length is more complicated here. Giving the size of
+ * struct sockaddr_un here and relying on the nul termination of
+ * sun_path does not work for paths in the abstract namespace. Note
+ * that we always assume the path is not empty and nul terminated */
+ *sockaddr_len = offsetof(struct sockaddr_un, sun_path) +
+ (sock_un->sun_path[0] == '\0'
+ ? (1 + strlen(&sock_un->sun_path[1]))
+ : strlen(sock_un->sun_path));
+ } else {
+ *sockaddr_len = sizeof(struct sockaddr_un);
}
break;
@@ -869,7 +889,14 @@ static void from_zval_write_control(const zval *arr,
}
if (entry->calc_space) {
- data_len = entry->calc_space(arr, ctx);
+ zval **data_elem;
+ /* arr must be an array at this point */
+ if (zend_hash_find(Z_ARRVAL_P(arr), "data", sizeof("data"),
+ (void**)&data_elem) == FAILURE) {
+ do_from_zval_err(ctx, "cmsghdr should have a 'data' element here");
+ return;
+ }
+ data_len = entry->calc_space(*data_elem, ctx);
if (ctx->err.has_error) {
return;
}
@@ -1370,7 +1397,7 @@ static void from_zval_write_fd_array_aux(zval **elem, unsigned i, void **args, s
return;
}
- if (php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&iarr[i],
+ 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;
diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c
index 801af0a4dd..b226d94715 100644
--- a/ext/sockets/sockets.c
+++ b/ext/sockets/sockets.c
@@ -1479,7 +1479,7 @@ PHP_FUNCTION(socket_strerror)
PHP_FUNCTION(socket_bind)
{
zval *arg1;
- php_sockaddr_storage sa_storage;
+ php_sockaddr_storage sa_storage = {0};
struct sockaddr *sock_type = (struct sockaddr*) &sa_storage;
php_socket *php_sock;
char *addr;
@@ -1497,10 +1497,19 @@ PHP_FUNCTION(socket_bind)
case AF_UNIX:
{
struct sockaddr_un *sa = (struct sockaddr_un *) sock_type;
- memset(sa, 0, sizeof(sa_storage));
+
sa->sun_family = AF_UNIX;
- snprintf(sa->sun_path, 108, "%s", addr);
- retval = bind(php_sock->bsd_socket, (struct sockaddr *) sa, SUN_LEN(sa));
+
+ if (addr_len >= sizeof(sa->sun_path)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Invalid path: too long (maximum size is %d)",
+ (int)sizeof(sa->sun_path) - 1);
+ RETURN_FALSE;
+ }
+ memcpy(&sa->sun_path, addr, addr_len);
+
+ retval = bind(php_sock->bsd_socket, (struct sockaddr *) sa,
+ offsetof(struct sockaddr_un, sun_path) + addr_len);
break;
}
@@ -1508,8 +1517,6 @@ PHP_FUNCTION(socket_bind)
{
struct sockaddr_in *sa = (struct sockaddr_in *) sock_type;
- memset(sa, 0, sizeof(sa_storage)); /* Apparently, Mac OSX needs this */
-
sa->sin_family = AF_INET;
sa->sin_port = htons((unsigned short) port);
@@ -1525,8 +1532,6 @@ PHP_FUNCTION(socket_bind)
{
struct sockaddr_in6 *sa = (struct sockaddr_in6 *) sock_type;
- memset(sa, 0, sizeof(sa_storage)); /* Apparently, Mac OSX needs this */
-
sa->sin6_family = AF_INET6;
sa->sin6_port = htons((unsigned short) port);
diff --git a/ext/sockets/tests/socket_abstract_path.phpt b/ext/sockets/tests/socket_abstract_path.phpt
new file mode 100644
index 0000000000..816e5c11bb
--- /dev/null
+++ b/ext/sockets/tests/socket_abstract_path.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Support for paths in the abstract namespace (bind, connect)
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets'))
+ die('skip sockets extension not available.');
+
+if (PHP_OS != 'Linux') {
+ die('skip For Linux only');
+}
+?>
+--FILE--
+<?php
+include __DIR__."/mcast_helpers.php.inc";
+
+$path = "\x00/foo_bar";
+
+echo "creating server socket\n";
+$servers = socket_create(AF_UNIX, SOCK_STREAM, 0) or die("err");
+socket_bind($servers, $path) or die("Could not bind");
+socket_listen($servers) or die("Could not listen");
+socket_set_nonblock($servers) or die("Could not put in non-blocking mode");
+
+echo "creating client socket\n";
+$clients = socket_create(AF_UNIX, SOCK_STREAM, 0) or die("err");
+socket_connect($clients, $path) or die("Error connecting");
+
+$conns = socket_accept($servers) or die("Could not accept connection");
+
+$r = socket_sendmsg($clients, [
+ //"name" => [ "addr" => $path, ],
+ "iov" => ["test ", "thing", "\n"],
+], 0);
+var_dump($r);
+checktimeout($conns, 500);
+
+if (!socket_recv($conns, $buf, 20, 0)) die("recv");
+print_r($buf);
+?>
+--EXPECTF--
+creating server socket
+creating client socket
+int(11)
+test thing
diff --git a/ext/sockets/tests/socket_abstract_path_sendmsg.phpt b/ext/sockets/tests/socket_abstract_path_sendmsg.phpt
new file mode 100644
index 0000000000..5a9275a26b
--- /dev/null
+++ b/ext/sockets/tests/socket_abstract_path_sendmsg.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Support for paths in the abstract namespace (bind, sendmsg, recvmsg)
+--SKIPIF--
+<?php
+if (!extension_loaded('sockets'))
+ die('skip sockets extension not available.');
+
+if (PHP_OS != 'Linux') {
+ die('skip For Linux only');
+}
+?>
+--FILE--
+<?php
+include __DIR__."/mcast_helpers.php.inc";
+
+$path = "\x00/bar_foo";
+
+echo "creating send socket\n";
+$sends1 = socket_create(AF_UNIX, SOCK_DGRAM, 0) or die("err");
+socket_set_nonblock($sends1) or die("Could not put in non-blocking mode");
+
+echo "creating receive socket\n";
+$s = socket_create(AF_UNIX, SOCK_DGRAM, 0) or die("err");
+socket_bind($s, $path) or die("err");
+
+$r = socket_sendmsg($sends1, [
+ "name" => [ "path" => $path],
+ "iov" => ["test ", "thing", "\n"],
+], 0);
+var_dump($r);
+checktimeout($s, 500);
+
+if (!socket_recv($s, $buf, 20, 0)) die("recv");
+print_r($buf);
+?>
+--EXPECTF--
+creating send socket
+creating receive socket
+int(11)
+test thing
diff --git a/ext/sockets/tests/socket_cmsg_rights.phpt b/ext/sockets/tests/socket_cmsg_rights.phpt
index 8290f03880..8c1734a568 100644
--- a/ext/sockets/tests/socket_cmsg_rights.phpt
+++ b/ext/sockets/tests/socket_cmsg_rights.phpt
@@ -84,6 +84,7 @@ Array
[0] => Resource id #%d
[1] => Resource id #%d
[2] => Resource id #%d
+ [3] => Resource id #%d
)
)