Patch bug41631.patch for OpenSSL related Bug #41631
Patch version 2014-09-19 15:13 UTC
Return to Bug #41631 |
Download this patch
Patch Revisions:
Developer: rdlowrey@php.net
From c033ddc428ed2954ecdfb9b78346458d655719f6 Mon Sep 17 00:00:00 2001
From: Daniel Lowrey <rdlowrey@php.net>
Date: Fri, 19 Sep 2014 10:46:13 -0400
Subject: [PATCH] Bug #41631: Fix EOF case when polling to observe socket timeout
---
ext/openssl/xp_ssl.c | 32 ++++++++++++++++++++++----------
1 files changed, 22 insertions(+), 10 deletions(-)
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
index b2a939d..b4de3d7 100644
--- a/ext/openssl/xp_ssl.c
+++ b/ext/openssl/xp_ssl.c
@@ -204,33 +204,45 @@ static size_t php_openssl_sockop_write(php_stream *stream, const char *buf, size
return didwrite;
}
-static void php_openssl_stream_wait_for_data(php_netstream_data_t *sock)
+static void php_openssl_stream_wait_for_data(SSL *ssl, php_netstream_data_t *sock TSRMLS_DC)
{
int retval;
+ int np_bytes = 0;
+ char peekbuf[128];
struct timeval *ptimeout;
if (sock->socket == -1) {
return;
}
-
+
sock->timeout_event = 0;
- if (sock->timeout.tv_sec == -1)
- ptimeout = NULL;
- else
- ptimeout = &sock->timeout;
+ /* We need to do a non-blocking peek first so we can avoid polling in the case of EOF
+ * but still observe the socket timeout otherwise.
+ */
+ php_set_sock_blocking(sock->socket, 0 TSRMLS_CC);
+ np_bytes = SSL_peek(ssl, peekbuf, sizeof(peekbuf));
+ php_set_sock_blocking(sock->socket, 1 TSRMLS_CC);
+ if (np_bytes <= 0) {
+ return;
+ }
+
+ ptimeout = (sock->timeout.tv_sec == -1) ? NULL : &sock->timeout;
while(1) {
retval = php_pollfd_for(sock->socket, PHP_POLLREADABLE, ptimeout);
- if (retval == 0)
+ if (retval == 0) {
sock->timeout_event = 1;
+ }
- if (retval >= 0)
+ if (retval >= 0) {
break;
+ }
- if (php_socket_errno() != EINTR)
+ if (php_socket_errno() != EINTR) {
break;
+ }
}
}
@@ -250,7 +262,7 @@ static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t coun
the actual read. If it times out we're finished.
*/
if (sock->is_blocked && SSL_pending(sslsock->ssl_handle) == 0) {
- php_openssl_stream_wait_for_data(sock);
+ php_openssl_stream_wait_for_data(sslsock->ssl_handle, sock);
if (sock->timeout_event) {
stream->eof = 1;
php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL read operation timed out");
--
1.7.1
|