summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Zelenka <bukka@php.net>2019-01-17 18:05:13 +0000
committerJakub Zelenka <bukka@php.net>2019-01-25 14:13:11 +0000
commitdc2ffdeed7d5c17eeb4f706f530eccafb425f92a (patch)
tree4273793f7b90dd9ff2c94a08d3a1025192894e33
parentd9b29029f9793ffdefbd575dd26cc54c78c0a1cf (diff)
downloadphp-git-dc2ffdeed7d5c17eeb4f706f530eccafb425f92a.tar.gz
Fix bug #77390 (feof might hang on TLS streams in case of fragmented TLS records)
Simplified version of the fix from Abyl Valg so credit to him.
-rw-r--r--NEWS4
-rw-r--r--ext/openssl/tests/bug77390.phpt11
-rw-r--r--ext/openssl/xp_ssl.c34
3 files changed, 25 insertions, 24 deletions
diff --git a/NEWS b/NEWS
index dbf4216bb5..3485917350 100644
--- a/NEWS
+++ b/NEWS
@@ -34,6 +34,10 @@ PHP NEWS
. Fixed bug #77361 (configure fails on 64-bit AIX when opcache enabled).
(Kevin Adler)
+- OpenSSL:
+ . Fixed bug #77390 (feof might hang on TLS streams in case of fragmented TLS
+ records). (Abyl Valg, Jakub Zelenka)
+
- PDO:
. Fixed bug #77273 (array_walk_recursive corrupts value types leading to PDO
failure). (Nikita)
diff --git a/ext/openssl/tests/bug77390.phpt b/ext/openssl/tests/bug77390.phpt
index d746a5d4aa..7f15329640 100644
--- a/ext/openssl/tests/bug77390.phpt
+++ b/ext/openssl/tests/bug77390.phpt
@@ -23,10 +23,16 @@ $clientCode = <<<'CODE'
$read = [$fp];
$buf = '';
+ $printed = false;
while (stream_select($read, $write, $except, 1000)) {
$chunk = stream_get_contents($fp, 4096);
- var_dump($chunk);
- $buf .= $chunk;
+ if ($chunk !== "") {
+ var_dump($chunk);
+ $buf .= $chunk;
+ } elseif (!$printed) {
+ $printed = true;
+ var_dump($chunk);
+ }
if ($buf === 'hello, world') {
break;
}
@@ -110,5 +116,4 @@ ServerClientTestCase::getInstance()->run($clientCode, [
?>
--EXPECT--
string(0) ""
-string(0) ""
string(12) "hello, world"
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
index a5a4c4dbfb..5117eb2e99 100644
--- a/ext/openssl/xp_ssl.c
+++ b/ext/openssl/xp_ssl.c
@@ -2405,30 +2405,22 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val
alive = 0;
} else if (php_pollfd_for(sslsock->s.socket, PHP_POLLREADABLE|POLLPRI, &tv) > 0) {
if (sslsock->ssl_active) {
- int n;
-
- do {
- n = SSL_peek(sslsock->ssl_handle, &buf, sizeof(buf));
- if (n <= 0) {
- int err = SSL_get_error(sslsock->ssl_handle, n);
-
- if (err == SSL_ERROR_SYSCALL) {
+ int n = SSL_peek(sslsock->ssl_handle, &buf, sizeof(buf));
+ if (n <= 0) {
+ int err = SSL_get_error(sslsock->ssl_handle, n);
+ switch (err) {
+ case SSL_ERROR_SYSCALL:
alive = php_socket_errno() == EAGAIN;
break;
- }
-
- if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
- /* re-negotiate */
- continue;
- }
-
- /* any other problem is a fatal error */
- alive = 0;
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ alive = 1;
+ break;
+ default:
+ /* any other problem is a fatal error */
+ alive = 0;
}
- /* either peek succeeded or there was an error; we
- * have set the alive flag appropriately */
- break;
- } while (1);
+ }
} else if (0 == recv(sslsock->s.socket, &buf, sizeof(buf), MSG_PEEK) && php_socket_errno() != EAGAIN) {
alive = 0;
}