com php-src: Fix bug 60471 by correctly identifying unused speculative preconnections: sapi/cli/php_cli_server.c sapi/cli/php _http_parser.c sapi/cli/php_http_parser.h

[email protected] (Sara Golemon)
Newsgroups php.cvs
Message-ID <[email protected]>
Commit:    fd0e71d001b76c0ce16bd2d2f7d80956ae9fc6f9
Author:    Sammy Kaye Powers <[email protected]>         Wed, 29 Mar 2017 09:27:18 -0500
Committer: Sara Golemon <[email protected]>      Tue, 11 Apr 2017 15:08:05 -0700
Parents:   8121cb50465268d645a61f79a8bec4d144700b34
Branches:  master

Link:       http://git.php.net/?p=php-src.git;a=commitdiff;h=fd0e71d001b76c0ce16bd2d2f7d80956ae9fc6f9

Log:
Fix bug 60471 by correctly identifying unused speculative preconnections

* Correctly identify unused speculative preconnections from browsers
  like Chrome and Firefox
* Add a new message to the debug level that is emitted when a TCP
  connection is closed without sending any request (a preconnection)
* Fix an issue where the existing debug messages were not being
  displayed even when debug mode was enabled

Bugs:
https://bugs.php.net/60471

Changed paths:
  M  sapi/cli/php_cli_server.c
  M  sapi/cli/php_http_parser.c
  M  sapi/cli/php_http_parser.h


Diff:
diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
index de4cfb2..1f4eb38 100644
--- a/sapi/cli/php_cli_server.c
+++ b/sapi/cli/php_cli_server.c
@@ -211,6 +211,8 @@ static php_cli_server_http_response_status_code_pair template_map[] = {
 static int php_cli_output_is_tty = OUTPUT_NOT_CHECKED;
 #endif
 
+static const char php_cli_server_request_error_unexpected_eof[] = "Unexpected EOF";
+
 static size_t php_cli_server_client_send_through(php_cli_server_client *client, const char *str, size_t str_len);
 static php_cli_server_chunk *php_cli_server_chunk_heap_new_self_contained(size_t len);
 static void php_cli_server_buffer_append(php_cli_server_buffer *buffer, php_cli_server_chunk *chunk);
@@ -1462,7 +1464,7 @@ static void normalize_vpath(char **retval, size_t *retval_len, const char *vpath
 #ifdef PHP_WIN32
 	{
 		char *p = decoded_vpath;
-		
+
 		do {
 			if (*p == '\\') {
 				*p = '/';
@@ -1677,7 +1679,7 @@ static int php_cli_server_client_read_request(php_cli_server_client *client, cha
 		*errstr = php_socket_strerror(err, NULL, 0);
 		return -1;
 	} else if (nbytes_read == 0) {
-		*errstr = estrdup("Unexpected EOF");
+		*errstr = estrdup(php_cli_server_request_error_unexpected_eof);
 		return -1;
 	}
 	client->parser.data = client;
@@ -1806,7 +1808,7 @@ static void php_cli_server_client_dtor(php_cli_server_client *client) /* {{{ */
 
 static void php_cli_server_close_connection(php_cli_server *server, php_cli_server_client *client) /* {{{ */
 {
-#ifdef DEBUG
+#if PHP_DEBUG
 	php_cli_server_logf("%s Closing", client->addr_str);
 #endif
 	zend_hash_index_del(&server->clients, client->sock);
@@ -2297,7 +2299,13 @@ static int php_cli_server_recv_event_read_request(php_cli_server *server, php_cl
 	char *errstr = NULL;
 	int status = php_cli_server_client_read_request(client, &errstr);
 	if (status < 0) {
-		php_cli_server_logf("%s Invalid request (%s)", client->addr_str, errstr);
+		if (strcmp(errstr, php_cli_server_request_error_unexpected_eof) == 0 && client->parser.state == s_start_req) {
+#if PHP_DEBUG
+			php_cli_server_logf("%s Closed without sending a request; it was probably just an unused speculative preconnection", client->addr_str);
+#endif
+		} else {
+			php_cli_server_logf("%s Invalid request (%s)", client->addr_str, errstr);
+		}
 		efree(errstr);
 		php_cli_server_close_connection(server, client);
 		return FAILURE;
@@ -2379,7 +2387,7 @@ static int php_cli_server_do_event_for_each_fd_callback(void *_params, php_socke
 			closesocket(client_sock);
 			return SUCCESS;
 		}
-#ifdef DEBUG
+#if PHP_DEBUG
 		php_cli_server_logf("%s Accepted", client->addr_str);
 #endif
 		zend_hash_index_update_ptr(&server->clients, client_sock, client);
diff --git a/sapi/cli/php_http_parser.c b/sapi/cli/php_http_parser.c
index 59361d0..63769c1 100644
--- a/sapi/cli/php_http_parser.c
+++ b/sapi/cli/php_http_parser.c
@@ -195,75 +195,6 @@ static const uint8_t normal_url_char[256] = {
         1,       1,       1,       1,       1,       1,       1,       0 };
 
 
-enum state
-  { s_dead = 1 /* important that this is > 0 */
-
-  , s_start_req_or_res
-  , s_res_or_resp_H
-  , s_start_res
-  , s_res_H
-  , s_res_HT
-  , s_res_HTT
-  , s_res_HTTP
-  , s_res_first_http_major
-  , s_res_http_major
-  , s_res_first_http_minor
-  , s_res_http_minor
-  , s_res_first_status_code
-  , s_res_status_code
-  , s_res_status
-  , s_res_line_almost_done
-
-  , s_start_req
-
-  , s_req_method
-  , s_req_spaces_before_url
-  , s_req_schema
-  , s_req_schema_slash
-  , s_req_schema_slash_slash
-  , s_req_host
-  , s_req_port
-  , s_req_path
-  , s_req_query_string_start
-  , s_req_query_string
-  , s_req_fragment_start
-  , s_req_fragment
-  , s_req_http_start
-  , s_req_http_H
-  , s_req_http_HT
-  , s_req_http_HTT
-  , s_req_http_HTTP
-  , s_req_first_http_major
-  , s_req_http_major
-  , s_req_first_http_minor
-  , s_req_http_minor
-  , s_req_line_almost_done
-
-  , s_header_field_start
-  , s_header_field
-  , s_header_value_start
-  , s_header_value
-
-  , s_header_almost_done
-
-  , s_headers_almost_done
-  /* Important: 's_headers_almost_done' must be the last 'header' state. All
-   * states beyond this must be 'body' states. It is used for overflow
-   * checking. See the PARSING_HEADER() macro.
-   */
-  , s_chunk_size_start
-  , s_chunk_size
-  , s_chunk_size_almost_done
-  , s_chunk_parameters
-  , s_chunk_data
-  , s_chunk_data_almost_done
-  , s_chunk_data_done
-
-  , s_body_identity
-  , s_body_identity_eof
-  };
-
-
 #define PARSING_HEADER(state) (state <= s_headers_almost_done && 0 == (parser->flags & F_TRAILING))
 
 
diff --git a/sapi/cli/php_http_parser.h b/sapi/cli/php_http_parser.h
index fa4873a..d2fa69b 100644
--- a/sapi/cli/php_http_parser.h
+++ b/sapi/cli/php_http_parser.h
@@ -110,6 +110,73 @@ enum php_http_method
 
 enum php_http_parser_type { PHP_HTTP_REQUEST, PHP_HTTP_RESPONSE, PHP_HTTP_BOTH };
 
+enum state
+  { s_dead = 1 /* important that this is > 0 */
+
+  , s_start_req_or_res
+  , s_res_or_resp_H
+  , s_start_res
+  , s_res_H
+  , s_res_HT
+  , s_res_HTT
+  , s_res_HTTP
+  , s_res_first_http_major
+  , s_res_http_major
+  , s_res_first_http_minor
+  , s_res_http_minor
+  , s_res_first_status_code
+  , s_res_status_code
+  , s_res_status
+  , s_res_line_almost_done
+
+  , s_start_req
+
+  , s_req_method
+  , s_req_spaces_before_url
+  , s_req_schema
+  , s_req_schema_slash
+  , s_req_schema_slash_slash
+  , s_req_host
+  , s_req_port
+  , s_req_path
+  , s_req_query_string_start
+  , s_req_query_string
+  , s_req_fragment_start
+  , s_req_fragment
+  , s_req_http_start
+  , s_req_http_H
+  , s_req_http_HT
+  , s_req_http_HTT
+  , s_req_http_HTTP
+  , s_req_first_http_major
+  , s_req_http_major
+  , s_req_first_http_minor
+  , s_req_http_minor
+  , s_req_line_almost_done
+
+  , s_header_field_start
+  , s_header_field
+  , s_header_value_start
+  , s_header_value
+
+  , s_header_almost_done
+
+  , s_headers_almost_done
+  /* Important: 's_headers_almost_done' must be the last 'header' state. All
+   * states beyond this must be 'body' states. It is used for overflow
+   * checking. See the PARSING_HEADER() macro.
+   */
+  , s_chunk_size_start
+  , s_chunk_size
+  , s_chunk_size_almost_done
+  , s_chunk_parameters
+  , s_chunk_data
+  , s_chunk_data_almost_done
+  , s_chunk_data_done
+
+  , s_body_identity
+  , s_body_identity_eof
+  };
 
 struct php_http_parser {
   /** PRIVATE **/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.