[php-src] master: Merge branch 'PHP-8.5'
Ilia Alshanetsky <[email protected]>
| Newsgroups | gmane.comp.php.cvs.general |
|---|---|
| Message-ID | <[email protected]> |
Author: Ilia Alshanetsky (iliaal)
Date: 2026-08-31T06:26:14-04:00
Commit: https://github.com/php/php-src/commit/0a3fe0a1150e8b857935a2bdee2b7f20c30599f9
Raw diff: https://github.com/php/php-src/commit/0a3fe0a1150e8b857935a2bdee2b7f20c30599f9.diff
Merge branch 'PHP-8.5'
* PHP-8.5:
Revert the mysqlnd wireprotocol length-encoded bounds checks
Changed paths:
D ext/mysqli/tests/mysqlnd_ok_packet_message_over_read.phpt
D ext/mysqli/tests/mysqlnd_rset_field_len_over_read.phpt
D ext/mysqli/tests/mysqlnd_rset_field_len_past_packet.phpt
M ext/mysqli/tests/fake_server.inc
M ext/mysqlnd/mysqlnd_wireprotocol.c
Diff:
diff --git a/ext/mysqli/tests/fake_server.inc b/ext/mysqli/tests/fake_server.inc
index 3af5c7459159..dad8bc52ddd1 100644
--- a/ext/mysqli/tests/fake_server.inc
+++ b/ext/mysqli/tests/fake_server.inc
@@ -721,19 +721,6 @@ function my_mysqli_test_auth_response_message_over_read(my_mysqli_fake_server_co
$conn->read();
}
-function my_mysqli_test_ok_packet_message_over_read(my_mysqli_fake_server_conn $conn): void
-{
- $p = new my_mysqli_fake_packet();
- $p->full = "08000001" . "00" . "00" . "00" . "0200" . "0000" . "fa";
-
- $conn->send_server_greetings();
- $conn->read_packets(1);
- $conn->send_server_ok();
- $conn->read_packets(1);
- $conn->send($p->to_bytes(), "Malicious OK Packet [message length past the packet size]");
- $conn->read();
-}
-
function my_mysqli_test_stmt_response_row_over_read_string(my_mysqli_fake_server_conn $conn): void
{
$rh = $conn->packet_generator->server_stmt_execute_items_response();
@@ -829,50 +816,6 @@ function my_mysqli_test_stmt_response_row_read_two_fields(my_mysqli_fake_server_
}
}
-function my_mysqli_test_rset_field_metadata_len_over_read(my_mysqli_fake_server_conn $conn): void
-{
- $rh = $conn->packet_generator->server_tabular_query_response();
-
- $qr2 = new my_mysqli_fake_packet();
- $qr2->packet_length = "0c0000";
- $qr2->packet_number = "02";
- $qr2->catalog_length_plus_name = "0161";
- $qr2->db_length_plus_name = "0162";
- $qr2->table_length_plus_name = "0163";
- $qr2->original_t = "0164";
- $qr2->name_length_plus_name = "0165";
- $qr2->original_n = "fcff";
-
- $conn->send_server_greetings();
- $conn->read_packets(1);
- $conn->send_server_ok();
- $conn->read_packets(1);
- $conn->send($conn->packets_to_bytes([$rh[0], $qr2]), "Malicious Tabular Response [metadata string length past the packet size]");
- $conn->read();
-}
-
-function my_mysqli_test_rset_field_metadata_len_past_packet(my_mysqli_fake_server_conn $conn): void
-{
- $rh = $conn->packet_generator->server_tabular_query_response();
-
- $qr2 = new my_mysqli_fake_packet();
- $qr2->packet_length = "0c0000";
- $qr2->packet_number = "02";
- $qr2->catalog_length_plus_name = "0161";
- $qr2->db_length_plus_name = "0162";
- $qr2->table_length_plus_name = "0163";
- $qr2->original_t = "0164";
- $qr2->name_length_plus_name = "0165";
- $qr2->original_n = "0561";
-
- $conn->send_server_greetings();
- $conn->read_packets(1);
- $conn->send_server_ok();
- $conn->read_packets(1);
- $conn->send($conn->packets_to_bytes([$rh[0], $qr2]), "Malicious Tabular Response [metadata string length past the packet size]");
- $conn->read();
-}
-
function my_mysqli_test_query_response_row_length_overflow(my_mysqli_fake_server_conn $conn): void
{
$rh = $conn->packet_generator->server_query_execute_data_response('strval');
diff --git a/ext/mysqli/tests/mysqlnd_ok_packet_message_over_read.phpt b/ext/mysqli/tests/mysqlnd_ok_packet_message_over_read.phpt
deleted file mode 100644
index 8364251e8df4..000000000000
--- a/ext/mysqli/tests/mysqlnd_ok_packet_message_over_read.phpt
+++ /dev/null
@@ -1,40 +0,0 @@
---TEST--
-mysqlnd OK packet message length buffer over-read
---EXTENSIONS--
-mysqli
---FILE--
-<?php
-require_once 'fake_server.inc';
-
-$servername = "127.0.0.1";
-$username = "root";
-$password = "";
-
-$process = run_fake_server_in_background('ok_packet_message_over_read');
-$process->wait();
-
-try {
- $conn = new mysqli( $servername, $username, $password, "", $process->getPort());
- var_dump($conn->select_db("test"));
-} catch (Exception $e) {
- echo $e::class, ": ", $e->getMessage(), PHP_EOL;
-}
-
-$process->terminate();
-
-print "done!";
-?>
---EXPECTF--
-[*] Server started on 127.0.0.1:%d
-[*] Connection established
-[*] Sending - Server Greeting: %s
-[*] Received: %s
-[*] Sending - Server OK: %s
-[*] Received: %s
-[*] Sending - Malicious OK Packet [message length past the packet size]: %s
-
-Warning: mysqli::select_db(): OK packet message length is past the packet size in %s on line %d
-
-Warning: mysqli::select_db(): Error while reading INIT_DB's response packet. PID=%d in %s on line %d
-mysqli_sql_exception: Malformed packet
-done!
diff --git a/ext/mysqli/tests/mysqlnd_rset_field_len_over_read.phpt b/ext/mysqli/tests/mysqlnd_rset_field_len_over_read.phpt
deleted file mode 100644
index 274468ded63d..000000000000
--- a/ext/mysqli/tests/mysqlnd_rset_field_len_over_read.phpt
+++ /dev/null
@@ -1,42 +0,0 @@
---TEST--
-mysqlnd result set field metadata string length buffer over-read (len clamped to packet size)
---EXTENSIONS--
-mysqli
---FILE--
-<?php
-require_once 'fake_server.inc';
-
-$servername = "127.0.0.1";
-$username = "root";
-$password = "";
-
-$process = run_fake_server_in_background('rset_field_metadata_len_over_read');
-$process->wait();
-
-try {
- $conn = new mysqli( $servername, $username, $password, "", $process->getPort());
- var_dump($conn->query("SELECT * from users"));
-} catch (Exception $e) {
- echo $e::class, ": ", $e->getMessage(), PHP_EOL;
-}
-
-$conn->close();
-
-$process->terminate();
-
-print "done!";
-?>
---EXPECTF--
-[*] Server started on 127.0.0.1:%d
-[*] Connection established
-[*] Sending - Server Greeting: 580000000a352e352e352d31302e352e31382d4d6172696144420003000000473e3f6047257c6700fef7080200ff81150000000000000f0000006c6b55463f49335f686c6431006d7973716c5f6e61746976655f70617373776f7264
-[*] Received: %s
-[*] Sending - Server OK: 0700000200000002000000
-[*] Received: %s
-[*] Sending - Malicious Tabular Response [metadata string length past the packet size]: 01000001010c00000201610162016301640165fcff
-
-Warning: mysqli::query(): Premature end of data (mysqlnd_wireprotocol.c:%d) in %s on line %d
-
-Warning: mysqli::query(): Result set field packet %d bytes shorter than expected in %s on line %d
-bool(false)
-done!
diff --git a/ext/mysqli/tests/mysqlnd_rset_field_len_past_packet.phpt b/ext/mysqli/tests/mysqlnd_rset_field_len_past_packet.phpt
deleted file mode 100644
index 020d28d95b25..000000000000
--- a/ext/mysqli/tests/mysqlnd_rset_field_len_past_packet.phpt
+++ /dev/null
@@ -1,40 +0,0 @@
---TEST--
-mysqlnd result set field metadata string length exceeds remaining packet bytes
---EXTENSIONS--
-mysqli
---FILE--
-<?php
-require_once 'fake_server.inc';
-
-$servername = "127.0.0.1";
-$username = "root";
-$password = "";
-
-$process = run_fake_server_in_background('rset_field_metadata_len_past_packet');
-$process->wait();
-
-try {
- $conn = new mysqli( $servername, $username, $password, "", $process->getPort());
- var_dump($conn->query("SELECT * from users"));
-} catch (Exception $e) {
- echo $e::class, ": ", $e->getMessage(), PHP_EOL;
-}
-
-$conn->close();
-
-$process->terminate();
-
-print "done!";
-?>
---EXPECTF--
-[*] Server started on 127.0.0.1:%d
-[*] Connection established
-[*] Sending - Server Greeting: %s
-[*] Received: %s
-[*] Sending - Server OK: %s
-[*] Received: %s
-[*] Sending - Malicious Tabular Response [metadata string length past the packet size]: %s
-
-Warning: mysqli::query(): Result set field metadata string length is past the packet size in %s on line %d
-bool(false)
-done!
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
index 094daa939aa4..b957240a4088 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
@@ -876,12 +876,7 @@ php_mysqlnd_ok_read(MYSQLND_CONN_DATA * conn, void * _packet)
/* There is a message */
if (packet->header.size > (size_t) (p - buf) && (net_len = php_mysqlnd_net_field_length(&p))) {
- if ((p - buf) > packet->header.size || packet->header.size - (p - buf) < net_len) {
- DBG_ERR_FMT("OK packet message length is past the packet size");
- php_error_docref(NULL, E_WARNING, "OK packet message length is past the packet size");
- DBG_RETURN(FAIL);
- }
- packet->message_len = net_len;
+ packet->message_len = MIN(net_len, buf_len - (p - begin));
packet->message = mnd_pestrndup((char *)p, packet->message_len, FALSE);
} else {
packet->message = NULL;
@@ -1174,17 +1169,10 @@ void php_mysqlnd_rset_header_free_mem(void * _packet)
/* }}} */
#define READ_RSET_FIELD(field_name) do { \
- BAIL_IF_NO_MORE_DATA; \
len = php_mysqlnd_net_field_length(&p); \
if (UNEXPECTED(len == MYSQLND_NULL_LENGTH)) { \
goto faulty_or_fake; \
} else if (len != 0) { \
- BAIL_IF_NO_MORE_DATA; \
- if (UNEXPECTED((p - begin) > packet->header.size || packet->header.size - (p - begin) < len)) { \
- DBG_ERR_FMT("Result set field metadata string length is past the packet size"); \
- php_error_docref(NULL, E_WARNING, "Result set field metadata string length is past the packet size"); \
- DBG_RETURN(FAIL); \
- } \
meta->field_name = (const char *)p; \
meta->field_name ## _length = len; \
p += len; \
@@ -1253,7 +1241,7 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet)
READ_RSET_FIELD(name);
READ_RSET_FIELD(org_name);
- BAIL_IF_NO_MORE_DATA;
+ /* 1 byte length */
if (UNEXPECTED(12 != *p)) {
DBG_ERR_FMT("Protocol error. Server sent false length. Expected 12 got %d", (int) *p);
php_error_docref(NULL, E_WARNING, "Protocol error. Server sent false length. Expected 12");