diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2020-10-28 17:12:35 +0100 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2020-10-28 17:15:27 +0100 |
commit | a66d73db4b2e2fcf03b9ecbbc196440eefeb6641 (patch) | |
tree | 810f20784d876a00d4c2982d21909d1eb1234a81 | |
parent | f547412cba52b499a4a130b0de1b6af2ea746e3a (diff) | |
download | php-git-a66d73db4b2e2fcf03b9ecbbc196440eefeb6641.tar.gz |
Fixed bug #65825
Set error_info when we fail to read a packet, instead of throwing
a warning. Additionally we also need to populate the right
error_info in rowp_read -- we'll later take the error from the
packet, not the connection.
No test case, as this is hard to reliably test. I'm using the
test case from:
https://github.com/php/php-src/pull/2131#issuecomment-538374838
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_wireprotocol.c | 17 |
2 files changed, 15 insertions, 4 deletions
@@ -44,6 +44,8 @@ PHP NEWS - PDO MySQL: . Fixed bug #66528 (No PDOException or errorCode if database becomes unavailable before PDO::commit). (Nikita) + . Fixed bug #65825 (PDOStatement::fetch() does not throw exception on broken + server connection). (Nikita) 29 Oct 2020, PHP 7.4.12 diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index b9a91c900e..786ba2a2e9 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -1354,6 +1354,15 @@ premature_end: } /* }}} */ +/* Like SET_CLIENT_ERROR, but for packet error_info. The type is the same, + * but only some parts of it are used. */ +static void set_packet_error( + MYSQLND_ERROR_INFO *info, unsigned err_no, const char *sqlstate, const char *error) +{ + info->error_no = err_no; + strlcpy(info->sqlstate, sqlstate, sizeof(info->sqlstate)); + strlcpy(info->error, error, sizeof(info->error)); +} /* {{{ php_mysqlnd_read_row_ex */ static enum_func_status @@ -1396,7 +1405,7 @@ php_mysqlnd_read_row_ex(MYSQLND_PFC * pfc, if (UNEXPECTED(PASS != (ret = pfc->data->m.receive(pfc, vio, p, header.size, stats, error_info)))) { DBG_ERR("Empty row packet body"); - php_error(E_WARNING, "Empty row packet body"); + set_packet_error(error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone); } else { while (header.size >= MYSQLND_MAX_PACKET_SIZE) { if (FAIL == mysqlnd_read_header(pfc, vio, &header, stats, error_info)) { @@ -1425,7 +1434,7 @@ php_mysqlnd_read_row_ex(MYSQLND_PFC * pfc, if (PASS != (ret = pfc->data->m.receive(pfc, vio, p, header.size, stats, error_info))) { DBG_ERR("Empty row packet body"); - php_error(E_WARNING, "Empty row packet body"); + set_packet_error(error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone); break; } } @@ -1720,8 +1729,8 @@ php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_ROW_BUFFER * row_buffer, zval * fi static enum_func_status php_mysqlnd_rowp_read(MYSQLND_CONN_DATA * conn, void * _packet) { - MYSQLND_PACKET_ROW *packet= (MYSQLND_PACKET_ROW *) _packet; - MYSQLND_ERROR_INFO * error_info = conn->error_info; + MYSQLND_PACKET_ROW *packet = (MYSQLND_PACKET_ROW *) _packet; + MYSQLND_ERROR_INFO * error_info = &packet->error_info; MYSQLND_PFC * pfc = conn->protocol_frame_codec; MYSQLND_VIO * vio = conn->vio; MYSQLND_STATS * stats = conn->stats; |