diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c index c4bd53d8c32..2a5924a531d 100644 --- a/ext/mysqlnd/mysqlnd_auth.c +++ b/ext/mysqlnd/mysqlnd_auth.c @@ -1073,6 +1073,13 @@ mysqlnd_caching_sha2_handle_server_response(struct st_mysqlnd_authentication_plu } switch (result_packet.response_code) { + case 0xFF: + if (result_packet.sqlstate[0]) { + strlcpy(conn->error_info->sqlstate, result_packet.sqlstate, sizeof(conn->error_info->sqlstate)); + DBG_ERR_FMT("ERROR:%u [SQLSTATE:%s] %s", result_packet.error_no, result_packet.sqlstate, result_packet.error); + } + SET_CLIENT_ERROR(conn->error_info, result_packet.error_no, UNKNOWN_SQLSTATE, result_packet.error); + DBG_RETURN(FAIL); case 0xFE: DBG_INF("auth switch response"); *new_auth_protocol = result_packet.new_auth_protocol; diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index 928e4f42012..ba289a6fce9 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -2178,7 +2178,6 @@ php_mysqlnd_cached_sha2_result_read(MYSQLND_CONN_DATA * conn, void * _packet) zend_uchar buf[SHA256_PK_REQUEST_RESP_BUFFER_SIZE]; zend_uchar *p = buf; const zend_uchar * const begin = buf; - uint8_t main_response_code; DBG_ENTER("php_mysqlnd_cached_sha2_result_read"); if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, sizeof(buf), "PROT_CACHED_SHA2_RESULT_PACKET", PROT_CACHED_SHA2_RESULT_PACKET)) { @@ -2186,12 +2185,18 @@ php_mysqlnd_cached_sha2_result_read(MYSQLND_CONN_DATA * conn, void * _packet) } BAIL_IF_NO_MORE_DATA; - main_response_code = uint1korr(p); + packet->response_code = uint1korr(p); p++; BAIL_IF_NO_MORE_DATA; - if (0xFE == main_response_code) { - packet->response_code = main_response_code; + if (ERROR_MARKER == packet->response_code) { + php_mysqlnd_read_error_from_line(p, packet->header.size - 1, + packet->error, sizeof(packet->error), + &packet->error_no, packet->sqlstate + ); + DBG_RETURN(PASS); + } + if (0xFE == packet->response_code) { /* Authentication Switch Response */ if (packet->header.size > (size_t) (p - buf)) { packet->new_auth_protocol = mnd_pestrdup((char *)p, FALSE); @@ -2209,10 +2214,11 @@ php_mysqlnd_cached_sha2_result_read(MYSQLND_CONN_DATA * conn, void * _packet) DBG_RETURN(PASS); } - if (0x1 != main_response_code) { - DBG_ERR_FMT("Unexpected response code %d", main_response_code); + if (0x1 != packet->response_code) { + DBG_ERR_FMT("Unexpected response code %d", packet->response_code); } + /* This is not really the response code, but we reuse the field. */ packet->response_code = uint1korr(p); p++; BAIL_IF_NO_MORE_DATA; diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.h b/ext/mysqlnd/mysqlnd_wireprotocol.h index 83ea5557dd5..c4ef4c3dade 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.h +++ b/ext/mysqlnd/mysqlnd_wireprotocol.h @@ -288,10 +288,15 @@ typedef struct st_mysqlnd_packet_cached_sha2_result { uint8_t request; zend_uchar * password; size_t password_len; + /* Used for auth switch request */ char *new_auth_protocol; size_t new_auth_protocol_len; zend_uchar *new_auth_protocol_data; size_t new_auth_protocol_data_len; + /* Used for error result */ + char error[MYSQLND_ERRMSG_SIZE+1]; + char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1]; + unsigned int error_no; } MYSQLND_PACKET_CACHED_SHA2_RESULT;