]> granicus.if.org Git - php/commitdiff
Fix stream_select() issue with OpenSSL buffer
authorChris Wright <github@daverandom.com>
Sat, 23 Aug 2014 00:40:19 +0000 (01:40 +0100)
committerChris Wright <daverandom@php.net>
Wed, 27 Aug 2014 12:25:50 +0000 (13:25 +0100)
Ensure data from OpenSSL internal buffer has been
transfered to PHP stream buffer before a select()
emulation operation is performed

Addresses bug #65137
https://bugs.php.net/bug.php?id=65137

Conflicts:
ext/openssl/xp_ssl.c

ext/openssl/xp_ssl.c
main/php_streams.h
main/streams/streams.c

index b7b8690165e1844ef611371257579d13f8b13fb4..956ffd0547fe4aa2a67d24551d8f7ffaf448deea 100644 (file)
@@ -871,6 +871,19 @@ static int php_openssl_sockop_cast(php_stream *stream, int castas, void **ret TS
 
                case PHP_STREAM_AS_FD_FOR_SELECT:
                        if (ret) {
+                               if (sslsock->ssl_active) {
+                                       /* OpenSSL has an internal buffer which select() cannot see. If we don't
+                                          fetch it into the stream's buffer, no activity will be reported on the
+                                          stream even though there is data waiting to be read - but we only fetch
+                                          the number of bytes OpenSSL has ready to give us since we weren't asked
+                                          for any data at this stage. This is only likely to cause issues with
+                                          non-blocking streams, but it's harmless to always do it. */
+                                       int bytes;
+                                       while ((bytes = SSL_pending(sslsock->ssl_handle)) > 0) {
+                                               php_stream_fill_read_buffer(stream, (size_t)bytes);
+                                       }
+                               }
+
                                *(int *)ret = sslsock->s.socket;
                        }
                        return SUCCESS;
index 2e4a3a2a18c141c9810bd21d101cad50ead9457f..89b877fdb167a69b84ec3bf0d6261de64cbad7d3 100644 (file)
@@ -301,6 +301,9 @@ PHPAPI size_t _php_stream_write(php_stream *stream, const char *buf, size_t coun
 #define php_stream_write_string(stream, str)   _php_stream_write(stream, str, strlen(str) TSRMLS_CC)
 #define php_stream_write(stream, buf, count)   _php_stream_write(stream, (buf), (count) TSRMLS_CC)
 
+PHPAPI void _php_stream_fill_read_buffer(php_stream *stream, size_t size TSRMLS_DC);
+#define php_stream_fill_read_buffer(stream, size)      _php_stream_fill_read_buffer((stream), (size) TSRMLS_CC)
+
 #ifdef ZTS
 PHPAPI size_t _php_stream_printf(php_stream *stream TSRMLS_DC, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
 #else
index 3fd4ab37968af5d5537498a9d8e557bfbf434f69..fbcc1ca4e365422d8e603ddfe1bf4b68e6dc9a4b 100644 (file)
@@ -573,7 +573,7 @@ fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remov
 
 /* {{{ generic stream operations */
 
-static void php_stream_fill_read_buffer(php_stream *stream, size_t size TSRMLS_DC)
+PHPAPI void _php_stream_fill_read_buffer(php_stream *stream, size_t size TSRMLS_DC)
 {
        /* allocate/fill the buffer */
 
@@ -741,7 +741,7 @@ PHPAPI size_t _php_stream_read(php_stream *stream, char *buf, size_t size TSRMLS
                                break;
                        }
                } else {
-                       php_stream_fill_read_buffer(stream, size TSRMLS_CC);
+                       php_stream_fill_read_buffer(stream, size);
 
                        toread = stream->writepos - stream->readpos;
                        if (toread > size) {
@@ -977,7 +977,7 @@ PHPAPI char *_php_stream_get_line(php_stream *stream, char *buf, size_t maxlen,
                                }
                        }
 
-                       php_stream_fill_read_buffer(stream, toread TSRMLS_CC);
+                       php_stream_fill_read_buffer(stream, toread);
 
                        if (stream->writepos - stream->readpos == 0) {
                                break;
@@ -1052,7 +1052,7 @@ PHPAPI char *php_stream_get_record(php_stream *stream, size_t maxlen, size_t *re
 
                to_read_now = MIN(maxlen - buffered_len, stream->chunk_size);
 
-               php_stream_fill_read_buffer(stream, buffered_len + to_read_now TSRMLS_CC);
+               php_stream_fill_read_buffer(stream, buffered_len + to_read_now);
 
                just_read = STREAM_BUFFERED_AMOUNT(stream) - buffered_len;