diff --git a/NEWS b/NEWS index d25d441ca8b5..1f009ffef87f 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,10 @@ PHP NEWS . Fixed bug GH-23301 (Nested "yield from" yields a value twice when the middle generator delegates again). (Lazizbek Ergashev) +- CLI: + . Fixed bug GH-23425 (sapi_cli_server_send_headers() does not check the + return value of php_cli_server_client_send_through()). (Lazizbek Ergashev) + - DOM: . Fixed a use-after-free when cloning a DOMNameSpaceNode after DOMDocument::xinclude(). (iliaal) diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index f4d29ce56855..36187aaeb035 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -177,6 +177,7 @@ typedef struct php_cli_server_client { zend_string *addr_str; php_http_parser parser; bool request_read; + bool headers_written; zend_string *current_header_name; zend_string *current_header_value; enum { HEADER_NONE=0, HEADER_FIELD, HEADER_VALUE } last_header_element; @@ -555,7 +556,7 @@ static int sapi_cli_server_send_headers(sapi_headers_struct *sapi_headers) /* {{ sapi_header_struct *h; zend_llist_position pos; - if (client == NULL || SG(request_info).no_headers) { + if (client == NULL || SG(request_info).no_headers || client->headers_written) { return SAPI_HEADER_SENT_SUCCESSFULLY; } @@ -578,10 +579,12 @@ static int sapi_cli_server_send_headers(sapi_headers_struct *sapi_headers) /* {{ } smart_str_appendl(&buffer, "\r\n", 2); - php_cli_server_client_send_through(client, ZSTR_VAL(buffer.s), ZSTR_LEN(buffer.s)); + size_t buffer_len = ZSTR_LEN(buffer.s); + bool sent = php_cli_server_client_send_through(client, ZSTR_VAL(buffer.s), buffer_len) == buffer_len; + client->headers_written = true; smart_str_free(&buffer); - return SAPI_HEADER_SENT_SUCCESSFULLY; + return sent ? SAPI_HEADER_SENT_SUCCESSFULLY : SAPI_HEADER_SEND_FAILED; } /* }}} */ @@ -1920,11 +1923,11 @@ static size_t php_cli_server_client_send_through(php_cli_server_client *client, } else { /* error or timeout */ php_handle_aborted_connection(); - return nbytes_left; + return str_len - nbytes_left; } } else { php_handle_aborted_connection(); - return nbytes_left; + return str_len - nbytes_left; } } nbytes_left -= nbytes_sent; @@ -1973,6 +1976,7 @@ static void php_cli_server_client_ctor(php_cli_server_client *client, php_cli_se php_http_parser_init(&client->parser, PHP_HTTP_REQUEST); client->request_read = false; + client->headers_written = false; client->last_header_element = HEADER_NONE; client->current_header_name = NULL; diff --git a/sapi/cli/tests/gh23425.phpt b/sapi/cli/tests/gh23425.phpt new file mode 100644 index 000000000000..e0de0982f7cc --- /dev/null +++ b/sapi/cli/tests/gh23425.phpt @@ -0,0 +1,39 @@ +--TEST-- +GH-23425 (sapi_cli_server_send_headers() does not check the return value of php_cli_server_client_send_through()) +--EXTENSIONS-- +sockets +--SKIPIF-- + +--FILE-- + 1, 'l_linger' => 0]); +socket_close($sock); + +$result_file = $info->docRoot . '/result.txt'; +for ($i = 0; $i < 40 && !file_exists($result_file); $i++) { + usleep(50000); +} + +echo file_get_contents($result_file), "\n"; +?> +--EXPECT-- +not-sent