summaryrefslogtreecommitdiff
path: root/ext/mysqlnd/mysqlnd_wireprotocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mysqlnd/mysqlnd_wireprotocol.c')
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.c152
1 files changed, 124 insertions, 28 deletions
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
index 15b64d9f6d..a6c0ac949b 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
@@ -287,7 +287,8 @@ mysqlnd_read_packet_header_and_body(MYSQLND_PACKET_HEADER * packet_header,
MYSQLND_STATS * stats,
MYSQLND_ERROR_INFO * error_info,
MYSQLND_CONNECTION_STATE * connection_state,
- zend_uchar * buf, size_t buf_size, const char * const packet_type_as_text,
+ zend_uchar * const buf, const size_t buf_size,
+ const char * const packet_type_as_text,
enum mysqlnd_packet_type packet_type)
{
DBG_ENTER("mysqlnd_read_packet_header_and_body");
@@ -618,10 +619,14 @@ size_t php_mysqlnd_auth_write(MYSQLND_CONN_DATA * conn, void * _packet)
const MYSQLND_CSTRING payload = {(char*) buffer + MYSQLND_HEADER_SIZE, p - (buffer + MYSQLND_HEADER_SIZE)};
const unsigned int silent = packet->silent;
- ret = conn->run_command(COM_CHANGE_USER, conn, payload, silent);
+ ret = conn->command->change_user(conn, payload, silent);
DBG_RETURN(ret == PASS? (p - buffer - MYSQLND_HEADER_SIZE) : 0);
} else {
- size_t sent = pfc->data->m.send(pfc, vio, buffer, p - buffer - MYSQLND_HEADER_SIZE, stats, error_info);
+ /*
+ The auth handshake packet has no command in it. Thus we can't go over conn->command directly.
+ Well, we can have a command->no_command(conn, payload)
+ */
+ const size_t sent = pfc->data->m.send(pfc, vio, buffer, p - buffer - MYSQLND_HEADER_SIZE, stats, error_info);
if (!sent) {
SET_CONNECTION_STATE(connection_state, CONN_QUIT_SENT);
}
@@ -766,7 +771,7 @@ php_mysqlnd_change_auth_response_write(MYSQLND_CONN_DATA * conn, void * _packet)
MYSQLND_VIO * vio = conn->vio;
MYSQLND_STATS * stats = conn->stats;
MYSQLND_CONNECTION_STATE * connection_state = &conn->state;
- zend_uchar * buffer = pfc->cmd_buffer.length >= packet->auth_data_len? pfc->cmd_buffer.buffer : mnd_emalloc(packet->auth_data_len);
+ zend_uchar * const buffer = pfc->cmd_buffer.length >= packet->auth_data_len? pfc->cmd_buffer.buffer : mnd_emalloc(packet->auth_data_len);
zend_uchar * p = buffer + MYSQLND_HEADER_SIZE; /* start after the header */
DBG_ENTER("php_mysqlnd_change_auth_response_write");
@@ -777,7 +782,11 @@ php_mysqlnd_change_auth_response_write(MYSQLND_CONN_DATA * conn, void * _packet)
}
{
- size_t sent = pfc->data->m.send(pfc, vio, buffer, p - buffer - MYSQLND_HEADER_SIZE, stats, error_info);
+ /*
+ The auth handshake packet has no command in it. Thus we can't go over conn->command directly.
+ Well, we can have a command->no_command(conn, payload)
+ */
+ const size_t sent = pfc->data->m.send(pfc, vio, buffer, p - buffer - MYSQLND_HEADER_SIZE, stats, error_info);
if (buffer != pfc->cmd_buffer.buffer) {
mnd_efree(buffer);
}
@@ -803,8 +812,8 @@ php_mysqlnd_ok_read(MYSQLND_CONN_DATA * conn, void * _packet)
MYSQLND_STATS * stats = conn->stats;
MYSQLND_CONNECTION_STATE * connection_state = &conn->state;
zend_uchar local_buf[OK_BUFFER_SIZE];
- size_t buf_len = pfc->cmd_buffer.buffer? pfc->cmd_buffer.length : OK_BUFFER_SIZE;
- zend_uchar * buf = pfc->cmd_buffer.buffer? (zend_uchar *) pfc->cmd_buffer.buffer : local_buf;
+ const size_t buf_len = pfc->cmd_buffer.buffer? pfc->cmd_buffer.length : OK_BUFFER_SIZE;
+ zend_uchar * const buf = pfc->cmd_buffer.buffer? (zend_uchar *) pfc->cmd_buffer.buffer : local_buf;
const zend_uchar * p = buf;
const zend_uchar * const begin = buf;
zend_ulong net_len;
@@ -897,8 +906,8 @@ php_mysqlnd_eof_read(MYSQLND_CONN_DATA * conn, void * _packet)
MYSQLND_VIO * vio = conn->vio;
MYSQLND_STATS * stats = conn->stats;
MYSQLND_CONNECTION_STATE * connection_state = &conn->state;
- size_t buf_len = pfc->cmd_buffer.length;
- zend_uchar * buf = (zend_uchar *) pfc->cmd_buffer.buffer;
+ const size_t buf_len = pfc->cmd_buffer.length;
+ zend_uchar * const buf = (zend_uchar *) pfc->cmd_buffer.buffer;
const zend_uchar * p = buf;
const zend_uchar * const begin = buf;
@@ -965,7 +974,7 @@ size_t php_mysqlnd_cmd_write(MYSQLND_CONN_DATA * conn, void * _packet)
MYSQLND_VIO * vio = conn->vio;
MYSQLND_STATS * stats = conn->stats;
MYSQLND_CONNECTION_STATE * connection_state = &conn->state;
- unsigned int error_reporting = EG(error_reporting);
+ const unsigned int error_reporting = EG(error_reporting);
size_t sent = 0;
DBG_ENTER("php_mysqlnd_cmd_write");
@@ -1034,8 +1043,8 @@ php_mysqlnd_rset_header_read(MYSQLND_CONN_DATA * conn, void * _packet)
MYSQLND_STATS * stats = conn->stats;
MYSQLND_CONNECTION_STATE * connection_state = &conn->state;
enum_func_status ret = PASS;
- size_t buf_len = pfc->cmd_buffer.length;
- zend_uchar * buf = (zend_uchar *) pfc->cmd_buffer.buffer;
+ const size_t buf_len = pfc->cmd_buffer.length;
+ zend_uchar * const buf = (zend_uchar *) pfc->cmd_buffer.buffer;
const zend_uchar * p = buf;
const zend_uchar * const begin = buf;
size_t len;
@@ -1175,8 +1184,9 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet)
MYSQLND_VIO * vio = conn->vio;
MYSQLND_STATS * stats = conn->stats;
MYSQLND_CONNECTION_STATE * connection_state = &conn->state;
- size_t buf_len = pfc->cmd_buffer.length, total_len = 0;
- zend_uchar * buf = (zend_uchar *) pfc->cmd_buffer.buffer;
+ const size_t buf_len = pfc->cmd_buffer.length;
+ size_t total_len = 0;
+ zend_uchar * const buf = (zend_uchar *) pfc->cmd_buffer.buffer;
const zend_uchar * p = buf;
const zend_uchar * const begin = buf;
char *root_ptr;
@@ -1353,7 +1363,7 @@ php_mysqlnd_read_row_ex(MYSQLND_PFC * pfc,
MYSQLND_ERROR_INFO * error_info,
MYSQLND_MEMORY_POOL * pool,
MYSQLND_ROW_BUFFER * buffer,
- size_t * data_size)
+ size_t * const data_size)
{
enum_func_status ret = PASS;
MYSQLND_PACKET_HEADER header;
@@ -1433,8 +1443,8 @@ php_mysqlnd_read_row_ex(MYSQLND_PFC * pfc,
/* {{{ php_mysqlnd_rowp_read_binary_protocol */
enum_func_status
php_mysqlnd_rowp_read_binary_protocol(MYSQLND_ROW_BUFFER * row_buffer, zval * fields,
- unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
- zend_bool as_int_or_float, MYSQLND_STATS * stats)
+ const unsigned int field_count, const MYSQLND_FIELD * const fields_metadata,
+ const zend_bool as_int_or_float, MYSQLND_STATS * const stats)
{
unsigned int i;
const zend_uchar * p = row_buffer->ptr;
@@ -1530,7 +1540,7 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_ROW_BUFFER * row_buffer, zval *
unsigned int i;
zval *current_field, *end_field, *start_field;
zend_uchar * p = row_buffer->ptr;
- size_t data_size = row_buffer->size;
+ const size_t data_size = row_buffer->size;
const zend_uchar * const packet_end = (zend_uchar*) p + data_size;
DBG_ENTER("php_mysqlnd_rowp_read_text_protocol_aux");
@@ -1677,8 +1687,8 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_ROW_BUFFER * row_buffer, zval *
/* {{{ php_mysqlnd_rowp_read_text_protocol_zval */
enum_func_status
php_mysqlnd_rowp_read_text_protocol_zval(MYSQLND_ROW_BUFFER * row_buffer, zval * fields,
- unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
- zend_bool as_int_or_float, MYSQLND_STATS * stats)
+ const unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
+ const zend_bool as_int_or_float, MYSQLND_STATS * stats)
{
enum_func_status ret;
DBG_ENTER("php_mysqlnd_rowp_read_text_protocol_zval");
@@ -1691,8 +1701,8 @@ php_mysqlnd_rowp_read_text_protocol_zval(MYSQLND_ROW_BUFFER * row_buffer, zval *
/* {{{ php_mysqlnd_rowp_read_text_protocol_c */
enum_func_status
php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_ROW_BUFFER * row_buffer, zval * fields,
- unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
- zend_bool as_int_or_float, MYSQLND_STATS * stats)
+ const unsigned int field_count, const MYSQLND_FIELD * const fields_metadata,
+ const zend_bool as_int_or_float, MYSQLND_STATS * const stats)
{
enum_func_status ret;
DBG_ENTER("php_mysqlnd_rowp_read_text_protocol_c");
@@ -1836,7 +1846,7 @@ php_mysqlnd_stats_read(MYSQLND_CONN_DATA * conn, void * _packet)
MYSQLND_VIO * vio = conn->vio;
MYSQLND_STATS * stats = conn->stats;
MYSQLND_CONNECTION_STATE * connection_state = &conn->state;
- size_t buf_len = pfc->cmd_buffer.length;
+ const size_t buf_len = pfc->cmd_buffer.length;
zend_uchar *buf = (zend_uchar *) pfc->cmd_buffer.buffer;
DBG_ENTER("php_mysqlnd_stats_read");
@@ -1883,7 +1893,7 @@ php_mysqlnd_prepare_read(MYSQLND_CONN_DATA * conn, void * _packet)
MYSQLND_STATS * stats = conn->stats;
MYSQLND_CONNECTION_STATE * connection_state = &conn->state;
/* In case of an error, we should have place to put it */
- size_t buf_len = pfc->cmd_buffer.length;
+ const size_t buf_len = pfc->cmd_buffer.length;
zend_uchar *buf = (zend_uchar *) pfc->cmd_buffer.buffer;
zend_uchar *p = buf;
const zend_uchar * const begin = buf;
@@ -1966,7 +1976,7 @@ php_mysqlnd_chg_user_read(MYSQLND_CONN_DATA * conn, void * _packet)
MYSQLND_STATS * stats = conn->stats;
MYSQLND_CONNECTION_STATE * connection_state = &conn->state;
/* There could be an error message */
- size_t buf_len = pfc->cmd_buffer.length;
+ const size_t buf_len = pfc->cmd_buffer.length;
zend_uchar *buf = (zend_uchar *) pfc->cmd_buffer.buffer;
zend_uchar *p = buf;
const zend_uchar * const begin = buf;
@@ -2123,6 +2133,75 @@ php_mysqlnd_sha256_pk_request_response_free_mem(void * _packet)
}
/* }}} */
+static
+size_t php_mysqlnd_cached_sha2_result_write(MYSQLND_CONN_DATA * conn, void * _packet)
+{
+ MYSQLND_PACKET_CACHED_SHA2_RESULT * packet= (MYSQLND_PACKET_CACHED_SHA2_RESULT *) _packet;
+ MYSQLND_ERROR_INFO * error_info = conn->error_info;
+ MYSQLND_PFC * pfc = conn->protocol_frame_codec;
+ MYSQLND_VIO * vio = conn->vio;
+ MYSQLND_STATS * stats = conn->stats;
+#if HAVE_COMPILER_C99_VLA
+ zend_uchar buffer[MYSQLND_HEADER_SIZE + packet->password_len + 1];
+#else
+ ALLOCA_FLAG(use_heap)
+ zend_uchar *buffer = do_alloca(MYSQLND_HEADER_SIZE + packet->password_len + 1, use_heap);
+#endif
+ size_t sent;
+
+ DBG_ENTER("php_mysqlnd_cached_sha2_result_write");
+
+ if (packet->request == 1) {
+ int1store(buffer + MYSQLND_HEADER_SIZE, '\2');
+ sent = pfc->data->m.send(pfc, vio, buffer, 1, stats, error_info);
+ } else {
+ memcpy(buffer + MYSQLND_HEADER_SIZE, packet->password, packet->password_len);
+ sent = pfc->data->m.send(pfc, vio, buffer, packet->password_len, stats, error_info);
+ }
+
+#if !HAVE_COMPILER_C99_VLA
+ free_alloca(buffer, use_heap);
+#endif
+
+ DBG_RETURN(sent);
+}
+
+static enum_func_status
+php_mysqlnd_cached_sha2_result_read(MYSQLND_CONN_DATA * conn, void * _packet)
+{
+ MYSQLND_PACKET_CACHED_SHA2_RESULT * packet= (MYSQLND_PACKET_CACHED_SHA2_RESULT *) _packet;
+ MYSQLND_ERROR_INFO * error_info = conn->error_info;
+ MYSQLND_PFC * pfc = conn->protocol_frame_codec;
+ MYSQLND_VIO * vio = conn->vio;
+ MYSQLND_STATS * stats = conn->stats;
+ MYSQLND_CONNECTION_STATE * connection_state = &conn->state;
+ zend_uchar buf[SHA256_PK_REQUEST_RESP_BUFFER_SIZE];
+ zend_uchar *p = buf;
+ const zend_uchar * const begin = buf;
+
+ 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)) {
+ DBG_RETURN(FAIL);
+ }
+ BAIL_IF_NO_MORE_DATA;
+
+ p++;
+ packet->response_code = uint1korr(p);
+ BAIL_IF_NO_MORE_DATA;
+
+ p++;
+ packet->result = uint1korr(p);
+ BAIL_IF_NO_MORE_DATA;
+
+ DBG_RETURN(PASS);
+
+premature_end:
+ DBG_ERR_FMT("OK packet %d bytes shorter than expected", p - begin - packet->header.size);
+ php_error_docref(NULL, E_WARNING, "SHA256_PK_REQUEST_RESPONSE packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
+ p - begin - packet->header.size);
+ DBG_RETURN(FAIL);
+}
+
/* {{{ packet_methods */
static
mysqlnd_packet_methods packet_methods[PROT_LAST] =
@@ -2201,9 +2280,14 @@ mysqlnd_packet_methods packet_methods[PROT_LAST] =
php_mysqlnd_sha256_pk_request_response_read,
NULL, /* write */
php_mysqlnd_sha256_pk_request_response_free_mem,
- } /* PROT_SHA256_PK_REQUEST_RESPONSE_PACKET */
+ }, /* PROT_SHA256_PK_REQUEST_RESPONSE_PACKET */
+ {
+ php_mysqlnd_cached_sha2_result_read,
+ php_mysqlnd_cached_sha2_result_write,
+ NULL
+ } /* PROT_CACHED_SHA2_RESULT_PACKET */
};
-/* }}} */
+/* }}} */
/* {{{ mysqlnd_protocol::init_greet_packet */
@@ -2385,6 +2469,17 @@ MYSQLND_METHOD(mysqlnd_protocol, init_sha256_pk_request_response_packet)(struct
}
/* }}} */
+/* {{{ mysqlnd_protocol::init_cached_sha2_result_packet */
+static void
+MYSQLND_METHOD(mysqlnd_protocol, init_cached_sha2_result_packet)(struct st_mysqlnd_packet_cached_sha2_result *packet)
+{
+ DBG_ENTER("mysqlnd_protocol::init_cached_sha2_result_packet");
+ memset(packet, 0, sizeof(*packet));
+ packet->header.m = &packet_methods[PROT_CACHED_SHA2_RESULT_PACKET];
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
/* {{{ mysqlnd_protocol::send_command */
static enum_func_status
@@ -2395,7 +2490,7 @@ MYSQLND_METHOD(mysqlnd_protocol, send_command)(
const zend_bool silent,
struct st_mysqlnd_connection_state * connection_state,
- MYSQLND_ERROR_INFO * error_info,
+ MYSQLND_ERROR_INFO * error_info,
MYSQLND_UPSERT_STATUS * upsert_status,
MYSQLND_STATS * stats,
func_mysqlnd_conn_data__send_close send_close,
@@ -2603,6 +2698,7 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_protocol_payload_decoder_factory)
MYSQLND_METHOD(mysqlnd_protocol, init_change_user_response_packet),
MYSQLND_METHOD(mysqlnd_protocol, init_sha256_pk_request_packet),
MYSQLND_METHOD(mysqlnd_protocol, init_sha256_pk_request_response_packet),
+ MYSQLND_METHOD(mysqlnd_protocol, init_cached_sha2_result_packet),
MYSQLND_METHOD(mysqlnd_protocol, send_command),
MYSQLND_METHOD(mysqlnd_protocol, send_command_handle_response),