diff options
author | Ondřej Surý <ondrej@sury.org> | 2013-05-09 17:32:08 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2013-05-09 17:32:08 +0200 |
commit | d674441ee1b9e7407f464b2692d9f5a0e2be3b4e (patch) | |
tree | cc4885524786f143bcc1af7d6c3f86fb571905de /ext/standard | |
parent | 367111123281ebfd2876d4c8cf33414b394f489a (diff) | |
download | php-d674441ee1b9e7407f464b2692d9f5a0e2be3b4e.tar.gz |
Imported Upstream version 5.5.0~rc1upstream/5.5.0_rc1
Diffstat (limited to 'ext/standard')
-rw-r--r-- | ext/standard/streamsfuncs.c | 21 | ||||
-rw-r--r-- | ext/standard/tests/file/bug24482.phpt | 5 | ||||
-rw-r--r-- | ext/standard/tests/streams/bug64770.phpt | 52 |
3 files changed, 74 insertions, 4 deletions
diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 21c55e404..209cb7f9b 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -601,7 +601,6 @@ static int stream_array_to_fd_set(zval *stream_array, fd_set *fds, php_socket_t { zval **elem; php_stream *stream; - php_socket_t this_fd; int cnt = 0; if (Z_TYPE_P(stream_array) != IS_ARRAY) { @@ -611,6 +610,11 @@ static int stream_array_to_fd_set(zval *stream_array, fd_set *fds, php_socket_t zend_hash_get_current_data(Z_ARRVAL_P(stream_array), (void **) &elem) == SUCCESS; zend_hash_move_forward(Z_ARRVAL_P(stream_array))) { + /* Temporary int fd is needed for the STREAM data type on windows, passing this_fd directly to php_stream_cast() + would eventually bring a wrong result on x64. php_stream_cast() casts to int internally, and this will leave + the higher bits of a SOCKET variable uninitialized on systems with little endian. */ + int tmp_fd; + php_stream_from_zval_no_verify(stream, elem); if (stream == NULL) { continue; @@ -620,7 +624,9 @@ static int stream_array_to_fd_set(zval *stream_array, fd_set *fds, php_socket_t * when casting. It is only used here so that the buffered data warning * is not displayed. * */ - if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1) && this_fd != -1) { + if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&tmp_fd, 1) && tmp_fd != -1) { + + php_socket_t this_fd = (php_socket_t)tmp_fd; PHP_SAFE_FD_SET(this_fd, fds); @@ -638,7 +644,6 @@ static int stream_array_from_fd_set(zval *stream_array, fd_set *fds TSRMLS_DC) zval **elem, **dest_elem; php_stream *stream; HashTable *new_hash; - php_socket_t this_fd; int ret = 0; if (Z_TYPE_P(stream_array) != IS_ARRAY) { @@ -655,6 +660,11 @@ static int stream_array_from_fd_set(zval *stream_array, fd_set *fds TSRMLS_DC) char *key; uint key_len; ulong num_ind; + /* Temporary int fd is needed for the STREAM data type on windows, passing this_fd directly to php_stream_cast() + would eventually bring a wrong result on x64. php_stream_cast() casts to int internally, and this will leave + the higher bits of a SOCKET variable uninitialized on systems with little endian. */ + int tmp_fd; + type = zend_hash_get_current_key_ex(Z_ARRVAL_P(stream_array), &key, &key_len, &num_ind, 0, NULL); @@ -672,7 +682,10 @@ static int stream_array_from_fd_set(zval *stream_array, fd_set *fds TSRMLS_DC) * when casting. It is only used here so that the buffered data warning * is not displayed. */ - if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1) && this_fd != -1) { + if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&tmp_fd, 1) && tmp_fd != -1) { + + php_socket_t this_fd = (php_socket_t)tmp_fd; + if (PHP_SAFE_FD_ISSET(this_fd, fds)) { if (type == HASH_KEY_IS_LONG) { zend_hash_index_update(new_hash, num_ind, (void *)elem, sizeof(zval *), (void **)&dest_elem); diff --git a/ext/standard/tests/file/bug24482.phpt b/ext/standard/tests/file/bug24482.phpt index f545f1add..9d0568af3 100644 --- a/ext/standard/tests/file/bug24482.phpt +++ b/ext/standard/tests/file/bug24482.phpt @@ -8,6 +8,11 @@ if (!function_exists("glob")) { ?> --FILE-- <?php + +// run this test in ext/standard/tests (see bug #64714) +chdir(__DIR__); // ensure in ext/standard/tests/file +chdir('..'); // move up to ext/standard/tests + $globdirs = glob("*", GLOB_ONLYDIR); $dirs = array(); diff --git a/ext/standard/tests/streams/bug64770.phpt b/ext/standard/tests/streams/bug64770.phpt new file mode 100644 index 000000000..785c4237a --- /dev/null +++ b/ext/standard/tests/streams/bug64770.phpt @@ -0,0 +1,52 @@ +--TEST-- +Bug #64770 stream_select() fails with pipes from proc_open() +--FILE-- +<?php + +$descs = array( + 0 => array('pipe', 'r'), // stdin + 1 => array('pipe', 'w'), // stdout + 2 => array('pipe', 'w'), // strerr +); + +$other_opts = array('suppress_errors' => false, 'binary_pipes' => true); + +$cmd = (substr(PHP_OS, 0, 3) == 'WIN') ? 'dir' : 'ls'; +$p = proc_open($cmd, $descs, $pipes, '.', NULL, $other_opts); + +if (is_resource($p)) { + $data = ''; + + while (1) { + $w = $e = NULL; + $n = stream_select($pipes, $w, $e, 300); + + if ($n === false) { + echo "no streams \n"; + break; + } else if ($n === 0) { + echo "process timed out\n"; + proc_terminate($p, 9); + break; + } else if ($n > 0) { + $line = fread($pipes[1], 8192); + if (strlen($line) == 0) { + /* EOF */ + break; + } + $data .= $line; + } + } + var_dump(strlen($data)); + + $ret = proc_close($p); + var_dump($ret); +} else { + echo "no process\n"; +} +?> +==DONE== +--EXPECTF-- +int(%d) +int(0) +==DONE== |