]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-5.6'
authorDaniel Lowrey <rdlowrey@php.net>
Mon, 9 Mar 2015 22:02:04 +0000 (16:02 -0600)
committerDaniel Lowrey <rdlowrey@php.net>
Mon, 9 Mar 2015 22:02:04 +0000 (16:02 -0600)
* PHP-5.6:
  Fix crypto stream timeout regressions

Conflicts:
ext/openssl/xp_ssl.c

1  2 
ext/openssl/xp_ssl.c

index a7902cd71c78d05c95133ba71f99f9395284d680,19a9b17abdae958943eb6b44d72f4e02efbdd334..1b5bba73e06d5aa182093977d794f3dc05d0301e
@@@ -2031,27 -1824,22 +2031,28 @@@ static size_t php_openssl_sockop_io(in
        if (sslsock->ssl_active) {
                int retry = 1;
                struct timeval start_time;
-               struct timeval *timeout;
-               int blocked = sslsock->s.is_blocked;
+               struct timeval *timeout = NULL;
+               int began_blocked = sslsock->s.is_blocked;
                int has_timeout = 0;
 +              int nr_bytes = 0;
 +
 +              /* prevent overflow in openssl */
 +              if (count > INT_MAX) {
 +                      count = INT_MAX;
 +              }
  
-               /* Begin by making the socket non-blocking. This allows us to check the timeout. */
-               if (SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0)) {
-                       sslsock->s.is_blocked = 0;
+               /* never use a timeout with non-blocking sockets */
+               if (began_blocked && &sslsock->s.timeout) {
+                       timeout = &sslsock->s.timeout;
                }
  
-               /* Get the timeout value (and make sure we are to check it. */
-               timeout = sslsock->is_client ? &sslsock->connect_timeout : &sslsock->s.timeout;
-               has_timeout = !sslsock->s.is_blocked && (timeout->tv_sec || timeout->tv_usec);
+               if (timeout && php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC) == SUCCESS) {
+                       sslsock->s.is_blocked = 0;
+               }
  
-               /* gettimeofday is not monotonic; using it here is not strictly correct */
-               if (has_timeout) {
+               if (!sslsock->s.is_blocked && timeout && (timeout->tv_sec || timeout->tv_usec)) {
+                       has_timeout = 1;
+                       /* gettimeofday is not monotonic; using it here is not strictly correct */
                        gettimeofday(&start_time, NULL);
                }
  
                                gettimeofday(&cur_time, NULL);
  
                                /* Determine how much time we've taken so far. */
-                               elapsed_time = subtract_timeval( cur_time, start_time );
+                               elapsed_time = subtract_timeval(cur_time, start_time);
  
                                /* and return an error if we've taken too long. */
-                               if (compare_timeval( elapsed_time, *timeout) > 0 ) {
+                               if (compare_timeval(elapsed_time, *timeout) > 0 ) {
                                        /* If the socket was originally blocking, set it back. */
-                                       if (blocked) {
+                                       if (began_blocked) {
 -                                              php_set_sock_blocking(sslsock->s.socket, 1 TSRMLS_CC);
 +                                              php_set_sock_blocking(sslsock->s.socket, 1);
                                                sslsock->s.is_blocked = 1;
                                        }
+                                       sslsock->s.timeout_event = 1;
                                        return -1;
                                }
                        }
                                int err = SSL_get_error(sslsock->ssl_handle, nr_bytes);
  
                                /* If we didn't get any error, then let's return it to PHP. */
 -                              if (err == SSL_ERROR_NONE)
 -                              break;
 +                              if (err == SSL_ERROR_NONE) {
 +                                      break;
 +                              }
  
                                /* Otherwise, we need to wait again (up to time_left or we get an error) */
-                               if (blocked) {
+                               if (began_blocked) {
                                        if (read) {
                                                php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_WRITE) ?
                                                        (POLLOUT|POLLPRI) : (POLLIN|POLLPRI), has_timeout ? &left_time : NULL);
                }
  
                /* And if we were originally supposed to be blocking, let's reset the socket to that. */
-               if (blocked) {
-                       php_set_sock_blocking(sslsock->s.socket, 1);
 -              if (began_blocked && php_set_sock_blocking(sslsock->s.socket, 1 TSRMLS_CC) == SUCCESS) {
++              if (began_blocked && php_set_sock_blocking(sslsock->s.socket, 1) == SUCCESS) {
                        sslsock->s.is_blocked = 1;
                }
 +
 +              return 0 > nr_bytes ? 0 : nr_bytes;
        } else {
 +              size_t nr_bytes = 0;
 +
                /*
 -               * This block is if we had no timeout... We will just sit and wait forever on the IO operation.
 +                       * This block is if we had no timeout... We will just sit and wait forever on the IO operation.
                 */
                if (read) {
 -                      nr_bytes = php_stream_socket_ops.read(stream, buf, count TSRMLS_CC);
 +                      nr_bytes = php_stream_socket_ops.read(stream, buf, count);
                } else {
 -                      nr_bytes = php_stream_socket_ops.write(stream, buf, count TSRMLS_CC);
 +                      nr_bytes = php_stream_socket_ops.write(stream, buf, count);
                }
 -      }
  
 -      /* PHP doesn't expect a negative return. */
 -      if (nr_bytes < 0) {
 -              nr_bytes = 0;
 +              return nr_bytes;
        }
 -
 -      return nr_bytes;
  }
  /* }}} */