From: Anatol Belski Date: Sat, 4 May 2013 10:16:38 +0000 (+0200) Subject: better fix for bug #64770 X-Git-Tag: php-5.3.26RC1~13 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5c701d19aca937e28fca32934719836991b40cf0;p=php better fix for bug #64770 --- diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 465d72d378..20e74fe1f3 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -611,7 +611,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 = 0; int cnt = 0; if (Z_TYPE_P(stream_array) != IS_ARRAY) { @@ -621,6 +620,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; @@ -630,7 +634,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); @@ -648,7 +654,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 = 0; int ret = 0; if (Z_TYPE_P(stream_array) != IS_ARRAY) { @@ -661,6 +666,11 @@ static int stream_array_from_fd_set(zval *stream_array, fd_set *fds TSRMLS_DC) 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; @@ -670,7 +680,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)) { zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem); if (dest_elem) { diff --git a/ext/standard/tests/streams/bug64770.phpt b/ext/standard/tests/streams/bug64770.phpt index ae738d83cd..785c4237a1 100644 --- a/ext/standard/tests/streams/bug64770.phpt +++ b/ext/standard/tests/streams/bug64770.phpt @@ -11,7 +11,8 @@ $descs = array( $other_opts = array('suppress_errors' => false, 'binary_pipes' => true); -$p = proc_open('dir', $descs, $pipes, '.', NULL, $other_opts); +$cmd = (substr(PHP_OS, 0, 3) == 'WIN') ? 'dir' : 'ls'; +$p = proc_open($cmd, $descs, $pipes, '.', NULL, $other_opts); if (is_resource($p)) { $data = '';