diff options
Diffstat (limited to 'ext/mysqlnd')
26 files changed, 1383 insertions, 1363 deletions
diff --git a/ext/mysqlnd/config9.m4 b/ext/mysqlnd/config9.m4 index 2c15c34e8d..3fc767b231 100644 --- a/ext/mysqlnd/config9.m4 +++ b/ext/mysqlnd/config9.m4 @@ -28,7 +28,17 @@ if test "$PHP_MYSQLND" != "no" || test "$PHP_MYSQLND_ENABLED" = "yes"; then if test "$PHP_MYSQLND_COMPRESSION_SUPPORT" != "no"; then AC_DEFINE([MYSQLND_COMPRESSION_WANTED], 1, [Enable compressed protocol support]) fi - AC_DEFINE([MYSQLND_SSL_SUPPORTED], 1, [Enable SSL support]) + + AC_DEFINE([MYSQLND_SSL_SUPPORTED], 1, [Enable core mysqlnd SSL code]) + + test -z "$PHP_OPENSSL" && PHP_OPENSSL=no + + if test "$PHP_OPENSSL" != "no" || test "$PHP_OPENSSL_DIR" != "no"; then + AC_CHECK_LIB(ssl, DSA_get_default_method, AC_DEFINE(HAVE_DSA_DEFAULT_METHOD, 1, [OpenSSL 0.9.7 or later])) + AC_CHECK_LIB(crypto, X509_free, AC_DEFINE(HAVE_DSA_DEFAULT_METHOD, 1, [OpenSSL 0.9.7 or later])) + + PHP_SETUP_OPENSSL(MYSQLND_SHARED_LIBADD, [AC_DEFINE(MYSQLND_HAVE_SSL,1,[Enable mysqlnd code that uses OpenSSL directly])]) + fi mysqlnd_sources="$mysqlnd_base_sources $mysqlnd_ps_sources" PHP_NEW_EXTENSION(mysqlnd, $mysqlnd_sources, $ext_shared) diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c index 900f8207b4..ad91212f2a 100644 --- a/ext/mysqlnd/mysqlnd.c +++ b/ext/mysqlnd/mysqlnd.c @@ -114,7 +114,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, free_contents)(MYSQLND_CONN_DATA * conn TSRMLS } if (conn->net) { - conn->net->m.free_contents(conn->net TSRMLS_CC); + conn->net->data->m.free_contents(conn->net TSRMLS_CC); } DBG_INF("Freeing memory of members"); @@ -303,17 +303,16 @@ MYSQLND_METHOD(mysqlnd_conn_data, simple_command_handle_response)(MYSQLND_CONN_D /* }}} */ -/* {{{ mysqlnd_conn_data::simple_command */ +/* {{{ mysqlnd_conn_data::simple_command_send_request */ static enum_func_status -MYSQLND_METHOD(mysqlnd_conn_data, simple_command)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, - const zend_uchar * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent, - zend_bool ignore_upsert_status TSRMLS_DC) +MYSQLND_METHOD(mysqlnd_conn_data, simple_command_send_request)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, + const zend_uchar * const arg, size_t arg_len, zend_bool silent, zend_bool ignore_upsert_status TSRMLS_DC) { enum_func_status ret = PASS; MYSQLND_PACKET_COMMAND * cmd_packet; - DBG_ENTER("mysqlnd_conn_data::simple_command"); - DBG_INF_FMT("command=%s ok_packet=%u silent=%u", mysqlnd_command_to_text[command], ok_packet, silent); + DBG_ENTER("mysqlnd_conn_data::simple_command_send_request"); + DBG_INF_FMT("command=%s silent=%u", mysqlnd_command_to_text[command], silent); switch (CONN_GET_STATE(conn)) { case CONN_READY: @@ -355,13 +354,30 @@ MYSQLND_METHOD(mysqlnd_conn_data, simple_command)(MYSQLND_CONN_DATA * conn, enum php_error(E_WARNING, "Error while sending %s packet. PID=%d", mysqlnd_command_to_text[command], getpid()); } CONN_SET_STATE(conn, CONN_QUIT_SENT); + conn->m->send_close(conn TSRMLS_CC); DBG_ERR("Server is gone"); ret = FAIL; - } else if (ok_packet != PROT_LAST) { + } + PACKET_FREE(cmd_packet); + DBG_RETURN(ret); +} +/* }}} */ + + +/* {{{ mysqlnd_conn_data::simple_command */ +static enum_func_status +MYSQLND_METHOD(mysqlnd_conn_data, simple_command)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, + const zend_uchar * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent, + zend_bool ignore_upsert_status TSRMLS_DC) +{ + enum_func_status ret; + DBG_ENTER("mysqlnd_conn_data::simple_command"); + + ret = conn->m->simple_command_send_request(conn, command, arg, arg_len, silent, ignore_upsert_status TSRMLS_CC); + if (PASS == ret && ok_packet != PROT_LAST) { ret = conn->m->simple_command_handle_response(conn, ok_packet, silent, command, ignore_upsert_status TSRMLS_CC); } - PACKET_FREE(cmd_packet); DBG_INF(ret == PASS ? "PASS":"FAIL"); DBG_RETURN(ret); } @@ -440,11 +456,7 @@ mysqlnd_switch_to_ssl_if_needed( if (options->charset_name && (charset = mysqlnd_find_charset_name(options->charset_name))) { auth_packet->charset_no = charset->nr; } else { -#if MYSQLND_UNICODE - auth_packet->charset_no = 200;/* utf8 - swedish collation, check mysqlnd_charset.c */ -#else auth_packet->charset_no = greet_packet->charset_no; -#endif } #ifdef MYSQLND_SSL_SUPPORTED @@ -453,13 +465,14 @@ mysqlnd_switch_to_ssl_if_needed( DBG_INF("Switching to SSL"); if (!PACKET_WRITE(auth_packet, conn)) { CONN_SET_STATE(conn, CONN_QUIT_SENT); + conn->m->send_close(conn TSRMLS_CC); SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone); goto end; } - conn->net->m.set_client_option(conn->net, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify TSRMLS_CC); + conn->net->data->m.set_client_option(conn->net, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify TSRMLS_CC); - if (FAIL == conn->net->m.enable_ssl(conn->net TSRMLS_CC)) { + if (FAIL == conn->net->data->m.enable_ssl(conn->net TSRMLS_CC)) { goto end; } } @@ -472,6 +485,159 @@ end: /* }}} */ +/* {{{ mysqlnd_conn_data::fetch_auth_plugin_by_name */ +static struct st_mysqlnd_authentication_plugin * +MYSQLND_METHOD(mysqlnd_conn_data, fetch_auth_plugin_by_name)(const char * const requested_protocol TSRMLS_DC) +{ + struct st_mysqlnd_authentication_plugin * auth_plugin; + char * plugin_name = NULL; + DBG_ENTER("mysqlnd_conn_data::fetch_auth_plugin_by_name"); + + mnd_sprintf(&plugin_name, 0, "auth_plugin_%s", requested_protocol); + DBG_INF_FMT("looking for %s auth plugin", plugin_name); + auth_plugin = mysqlnd_plugin_find(plugin_name); + mnd_sprintf_free(plugin_name); + + DBG_RETURN(auth_plugin); +} +/* }}} */ + + +/* {{{ mysqlnd_run_authentication */ +static enum_func_status +mysqlnd_run_authentication( + MYSQLND_CONN_DATA * conn, + const char * const user, + const char * const passwd, + const size_t passwd_len, + const char * const db, + const size_t db_len, + const zend_uchar * const auth_plugin_data, + const size_t auth_plugin_data_len, + const char * const auth_protocol, + unsigned int charset_no, + const MYSQLND_OPTIONS * const options, + unsigned long mysql_flags, + zend_bool silent, + zend_bool is_change_user + TSRMLS_DC) +{ + enum_func_status ret = FAIL; + zend_bool first_call = TRUE; + + char * switch_to_auth_protocol = NULL; + size_t switch_to_auth_protocol_len = 0; + char * requested_protocol = NULL; + zend_uchar * plugin_data; + size_t plugin_data_len; + + DBG_ENTER("mysqlnd_run_authentication"); + + plugin_data_len = auth_plugin_data_len; + plugin_data = mnd_emalloc(plugin_data_len + 1); + if (!plugin_data) { + goto end; + } + memcpy(plugin_data, auth_plugin_data, plugin_data_len); + plugin_data[plugin_data_len] = '\0'; + + requested_protocol = mnd_pestrdup(auth_protocol? auth_protocol : MYSQLND_DEFAULT_AUTH_PROTOCOL, FALSE); + if (!requested_protocol) { + goto end; + } + + do { + struct st_mysqlnd_authentication_plugin * auth_plugin = conn->m->fetch_auth_plugin_by_name(requested_protocol TSRMLS_CC); + + if (!auth_plugin) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "The server requested authentication method unknown to the client [%s]", requested_protocol); + SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "The server requested authentication method umknown to the client"); + goto end; + } + DBG_INF("plugin found"); + + { + zend_uchar * switch_to_auth_protocol_data = NULL; + size_t switch_to_auth_protocol_data_len = 0; + zend_uchar * scrambled_data = NULL; + size_t scrambled_data_len = 0; + + switch_to_auth_protocol = NULL; + switch_to_auth_protocol_len = 0; + + if (conn->auth_plugin_data) { + mnd_pefree(conn->auth_plugin_data, conn->persistent); + conn->auth_plugin_data = NULL; + } + conn->auth_plugin_data_len = plugin_data_len; + conn->auth_plugin_data = mnd_pemalloc(conn->auth_plugin_data_len, conn->persistent); + if (!conn->auth_plugin_data) { + SET_OOM_ERROR(*conn->error_info); + goto end; + } + memcpy(conn->auth_plugin_data, plugin_data, plugin_data_len); + + DBG_INF_FMT("salt(%d)=[%.*s]", plugin_data_len, plugin_data_len, plugin_data); + /* The data should be allocated with malloc() */ + scrambled_data = + auth_plugin->methods.get_auth_data(NULL, &scrambled_data_len, conn, user, passwd, passwd_len, + plugin_data, plugin_data_len, options, &conn->net->data->options, mysql_flags TSRMLS_CC); + if (conn->error_info->error_no) { + goto end; + } + if (FALSE == is_change_user) { + ret = mysqlnd_auth_handshake(conn, user, passwd, passwd_len, db, db_len, options, mysql_flags, + charset_no, + first_call, + requested_protocol, + scrambled_data, scrambled_data_len, + &switch_to_auth_protocol, &switch_to_auth_protocol_len, + &switch_to_auth_protocol_data, &switch_to_auth_protocol_data_len + TSRMLS_CC); + } else { + ret = mysqlnd_auth_change_user(conn, user, strlen(user), passwd, passwd_len, db, db_len, silent, + first_call, + requested_protocol, + scrambled_data, scrambled_data_len, + &switch_to_auth_protocol, &switch_to_auth_protocol_len, + &switch_to_auth_protocol_data, &switch_to_auth_protocol_data_len + TSRMLS_CC); + } + first_call = FALSE; + free(scrambled_data); + + DBG_INF_FMT("switch_to_auth_protocol=%s", switch_to_auth_protocol? switch_to_auth_protocol:"n/a"); + if (requested_protocol && switch_to_auth_protocol) { + mnd_efree(requested_protocol); + requested_protocol = switch_to_auth_protocol; + } + + if (plugin_data) { + mnd_efree(plugin_data); + } + plugin_data_len = switch_to_auth_protocol_data_len; + plugin_data = switch_to_auth_protocol_data; + } + DBG_INF_FMT("conn->error_info->error_no = %d", conn->error_info->error_no); + } while (ret == FAIL && conn->error_info->error_no == 0 && switch_to_auth_protocol != NULL); + + if (ret == PASS) { + DBG_INF_FMT("saving requested_protocol=%s", requested_protocol); + conn->m->set_client_option(conn, MYSQLND_OPT_AUTH_PROTOCOL, requested_protocol TSRMLS_CC); + } +end: + if (plugin_data) { + mnd_efree(plugin_data); + } + if (requested_protocol) { + mnd_efree(requested_protocol); + } + + DBG_RETURN(ret); +} +/* }}} */ + + /* {{{ mysqlnd_connect_run_authentication */ static enum_func_status mysqlnd_connect_run_authentication( @@ -491,116 +657,160 @@ mysqlnd_connect_run_authentication( ret = mysqlnd_switch_to_ssl_if_needed(conn, greet_packet, options, mysql_flags TSRMLS_CC); if (PASS == ret) { - zend_bool first_call = TRUE; + ret = mysqlnd_run_authentication(conn, user, passwd, passwd_len, db, db_len, + greet_packet->auth_plugin_data, greet_packet->auth_plugin_data_len, greet_packet->auth_protocol, + greet_packet->charset_no, options, mysql_flags, FALSE /*silent*/, FALSE/*is_change*/ TSRMLS_CC); + } + DBG_RETURN(ret); +} +/* }}} */ - char * switch_to_auth_protocol = NULL; - size_t switch_to_auth_protocol_len = 0; - char * requested_protocol = NULL; - zend_uchar * plugin_data; - size_t plugin_data_len; - plugin_data_len = greet_packet->auth_plugin_data_len; - plugin_data = mnd_emalloc(plugin_data_len + 1); - if (!plugin_data) { - ret = FAIL; - goto end; - } - memcpy(plugin_data, greet_packet->auth_plugin_data, plugin_data_len); - plugin_data[plugin_data_len] = '\0'; +/* {{{ mysqlnd_conn_data::execute_init_commands */ +static enum_func_status +MYSQLND_METHOD(mysqlnd_conn_data, execute_init_commands)(MYSQLND_CONN_DATA * conn TSRMLS_DC) +{ + enum_func_status ret = PASS; - requested_protocol = mnd_pestrdup(greet_packet->auth_protocol? greet_packet->auth_protocol: "mysql_native_password", FALSE); - if (!requested_protocol) { - ret = FAIL; - goto end; + DBG_ENTER("mysqlnd_conn_data::execute_init_commands"); + if (conn->options->init_commands) { + unsigned int current_command = 0; + for (; current_command < conn->options->num_commands; ++current_command) { + const char * const command = conn->options->init_commands[current_command]; + if (command) { + MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_EXECUTED_COUNT); + if (PASS != conn->m->query(conn, command, strlen(command) TSRMLS_CC)) { + MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_FAILED_COUNT); + ret = FAIL; + break; + } + if (conn->last_query_type == QUERY_SELECT) { + MYSQLND_RES * result = conn->m->use_result(conn TSRMLS_CC); + if (result) { + result->m.free_result(result, TRUE TSRMLS_CC); + } + } + } } + } + DBG_RETURN(ret); +} +/* }}} */ - do { - struct st_mysqlnd_authentication_plugin * auth_plugin; - { - char * plugin_name = NULL; - mnd_sprintf(&plugin_name, 0, "auth_plugin_%s", requested_protocol); +/* {{{ mysqlnd_conn_data::get_updated_connect_flags */ +static unsigned int +MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags)(MYSQLND_CONN_DATA * conn, unsigned int mysql_flags TSRMLS_DC) +{ + MYSQLND_NET * net = conn->net; - DBG_INF_FMT("looking for %s auth plugin", plugin_name); - auth_plugin = mysqlnd_plugin_find(plugin_name); - mnd_sprintf_free(plugin_name); + DBG_ENTER("mysqlnd_conn_data::get_updated_connect_flags"); + /* we allow load data local infile by default */ + mysql_flags |= MYSQLND_CAPABILITIES; - if (!auth_plugin) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The server requested authentication method unknown to the client [%s]", requested_protocol); - SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "The server requested authentication method umknown to the client"); - break; - } - } - DBG_INF("plugin found"); + if (PG(open_basedir) && strlen(PG(open_basedir))) { + mysql_flags ^= CLIENT_LOCAL_FILES; + } - { - zend_uchar * switch_to_auth_protocol_data = NULL; - size_t switch_to_auth_protocol_data_len = 0; - zend_uchar * scrambled_data = NULL; - size_t scrambled_data_len = 0; +#ifndef MYSQLND_COMPRESSION_ENABLED + if (mysql_flags & CLIENT_COMPRESS) { + mysql_flags &= ~CLIENT_COMPRESS; + } +#else + if (net && net->data->options.flags & MYSQLND_NET_FLAG_USE_COMPRESSION) { + mysql_flags |= CLIENT_COMPRESS; + } +#endif +#ifndef MYSQLND_SSL_SUPPORTED + if (mysql_flags & CLIENT_SSL) { + mysql_flags &= ~CLIENT_SSL; + } +#else + if (net && (net->data->options.ssl_key || net->data->options.ssl_cert || + net->data->options.ssl_ca || net->data->options.ssl_capath || net->data->options.ssl_cipher)) + { + mysql_flags |= CLIENT_SSL; + } +#endif - switch_to_auth_protocol = NULL; - switch_to_auth_protocol_len = 0; + DBG_RETURN(mysql_flags); +} +/* }}} */ - if (conn->auth_plugin_data) { - mnd_pefree(conn->auth_plugin_data, conn->persistent); - conn->auth_plugin_data = NULL; - } - conn->auth_plugin_data_len = plugin_data_len; - conn->auth_plugin_data = mnd_pemalloc(conn->auth_plugin_data_len, conn->persistent); - if (!conn->auth_plugin_data) { - SET_OOM_ERROR(*conn->error_info); - goto end; - } - memcpy(conn->auth_plugin_data, plugin_data, plugin_data_len); - DBG_INF_FMT("salt=[%*s]", plugin_data_len - 1, plugin_data); - /* The data should be allocated with malloc() */ - scrambled_data = - auth_plugin->methods.get_auth_data(NULL, &scrambled_data_len, conn, user, passwd, passwd_len, - plugin_data, plugin_data_len, options, mysql_flags TSRMLS_CC); +/* {{{ mysqlnd_conn_data::connect_handshake */ +static enum_func_status +MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn, + const char * const host, const char * const user, + const char * const passwd, const unsigned int passwd_len, + const char * const db, const unsigned int db_len, + const unsigned int mysql_flags TSRMLS_DC) +{ + MYSQLND_PACKET_GREET * greet_packet; + MYSQLND_NET * net = conn->net; + DBG_ENTER("mysqlnd_conn_data::connect_handshake"); - ret = mysqlnd_auth_handshake(conn, user, passwd, passwd_len, db, db_len, options, mysql_flags, - greet_packet->charset_no, - first_call, - requested_protocol, - scrambled_data, scrambled_data_len, - &switch_to_auth_protocol, &switch_to_auth_protocol_len, - &switch_to_auth_protocol_data, &switch_to_auth_protocol_data_len - TSRMLS_CC); - first_call = FALSE; - free(scrambled_data); + greet_packet = conn->protocol->m.get_greet_packet(conn->protocol, FALSE TSRMLS_CC); + if (!greet_packet) { + SET_OOM_ERROR(*conn->error_info); + DBG_RETURN(FAIL); /* OOM */ + } - DBG_INF_FMT("switch_to_auth_protocol=%s", switch_to_auth_protocol? switch_to_auth_protocol:"n/a"); - if (requested_protocol && switch_to_auth_protocol) { - mnd_efree(requested_protocol); - requested_protocol = switch_to_auth_protocol; - } + if (FAIL == net->data->m.connect_ex(conn->net, conn->scheme, conn->scheme_len, conn->persistent, + conn->stats, conn->error_info TSRMLS_CC)) + { + goto err; + } - if (plugin_data) { - mnd_efree(plugin_data); - } - plugin_data_len = switch_to_auth_protocol_data_len; - plugin_data = switch_to_auth_protocol_data; - } - DBG_INF_FMT("conn->error_info->error_no = %d", conn->error_info->error_no); - } while (ret == FAIL && conn->error_info->error_no == 0 && switch_to_auth_protocol != NULL); - if (plugin_data) { - mnd_efree(plugin_data); - } - - if (ret == PASS) { - DBG_INF_FMT("saving requested_protocol=%s", requested_protocol); - conn->m->set_client_option(conn, MYSQLND_OPT_AUTH_PROTOCOL, requested_protocol TSRMLS_CC); - } + DBG_INF_FMT("stream=%p", net->data->m.get_stream(net TSRMLS_CC)); - if (requested_protocol) { - mnd_efree(requested_protocol); - } + if (FAIL == PACKET_READ(greet_packet, conn)) { + DBG_ERR("Error while reading greeting packet"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading greeting packet. PID=%d", getpid()); + goto err; + } else if (greet_packet->error_no) { + DBG_ERR_FMT("errorno=%u error=%s", greet_packet->error_no, greet_packet->error); + SET_CLIENT_ERROR(*conn->error_info, greet_packet->error_no, greet_packet->sqlstate, greet_packet->error); + goto err; + } else if (greet_packet->pre41) { + DBG_ERR_FMT("Connecting to 3.22, 3.23 & 4.0 is not supported. Server is %-.32s", greet_packet->server_version); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connecting to 3.22, 3.23 & 4.0 " + " is not supported. Server is %-.32s", greet_packet->server_version); + SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, + "Connecting to 3.22, 3.23 & 4.0 servers is not supported"); + goto err; } -end: - DBG_RETURN(ret); + + conn->thread_id = greet_packet->thread_id; + conn->protocol_version = greet_packet->protocol_version; + conn->server_version = mnd_pestrdup(greet_packet->server_version, conn->persistent); + + conn->greet_charset = mysqlnd_find_charset_nr(greet_packet->charset_no); + if (!conn->greet_charset) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Server sent charset (%d) unknown to the client. Please, report to the developers", greet_packet->charset_no); + SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, + "Server sent charset unknown to the client. Please, report to the developers"); + goto err; + } + + if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len, + greet_packet, conn->options, mysql_flags TSRMLS_CC)) + { + goto err; + } + conn->client_flag = mysql_flags; + conn->server_capabilities = greet_packet->server_capabilities; + conn->upsert_status->warning_count = 0; + conn->upsert_status->server_status = greet_packet->server_status; + conn->upsert_status->affected_rows = 0; + + PACKET_FREE(greet_packet); + DBG_RETURN(PASS); +err: + PACKET_FREE(greet_packet); + DBG_RETURN(FAIL); } /* }}} */ @@ -623,10 +833,10 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn, zend_bool reconnect = FALSE; zend_bool saved_compression = FALSE; zend_bool local_tx_started = FALSE; - - MYSQLND_PACKET_GREET * greet_packet = NULL; + MYSQLND_NET * net = conn->net; DBG_ENTER("mysqlnd_conn_data::connect"); + DBG_INF_FMT("conn=%p", conn); if (PASS != conn->m->local_tx_start(conn, this_func TSRMLS_CC)) { goto err; @@ -655,14 +865,17 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn, MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_PERSISTENT_CONNECTIONS); } /* Now reconnect using the same handle */ - if (conn->net->compressed) { + if (net->data->compressed) { /* we need to save the state. As we will re-connect, net->compressed should be off, or we will look for a compression header as part of the greet message, but there will be none. */ saved_compression = TRUE; - conn->net->compressed = FALSE; + net->data->compressed = FALSE; + } + if (net->data->ssl) { + net->data->ssl = FALSE; } } else { unsigned int max_allowed_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE; @@ -685,6 +898,8 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn, DBG_INF_FMT("no db given, using empty string"); db = ""; db_len = 0; + } else { + mysql_flags |= CLIENT_CONNECT_WITH_DB; } host_len = strlen(host); @@ -728,84 +943,9 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn, } } - greet_packet = conn->protocol->m.get_greet_packet(conn->protocol, FALSE TSRMLS_CC); - if (!greet_packet) { - SET_OOM_ERROR(*conn->error_info); - goto err; /* OOM */ - } + mysql_flags = conn->m->get_updated_connect_flags(conn, mysql_flags TSRMLS_CC); - if (FAIL == conn->net->m.connect_ex(conn->net, conn->scheme, conn->scheme_len, conn->persistent, - conn->stats, conn->error_info TSRMLS_CC)) - { - goto err; - } - - DBG_INF_FMT("stream=%p", conn->net->stream); - - if (FAIL == PACKET_READ(greet_packet, conn)) { - DBG_ERR("Error while reading greeting packet"); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading greeting packet. PID=%d", getpid()); - goto err; - } else if (greet_packet->error_no) { - DBG_ERR_FMT("errorno=%u error=%s", greet_packet->error_no, greet_packet->error); - SET_CLIENT_ERROR(*conn->error_info, greet_packet->error_no, greet_packet->sqlstate, greet_packet->error); - goto err; - } else if (greet_packet->pre41) { - DBG_ERR_FMT("Connecting to 3.22, 3.23 & 4.0 is not supported. Server is %-.32s", greet_packet->server_version); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connecting to 3.22, 3.23 & 4.0 " - " is not supported. Server is %-.32s", greet_packet->server_version); - SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, - "Connecting to 3.22, 3.23 & 4.0 servers is not supported"); - goto err; - } - - conn->thread_id = greet_packet->thread_id; - conn->protocol_version = greet_packet->protocol_version; - conn->server_version = mnd_pestrdup(greet_packet->server_version, conn->persistent); - - conn->greet_charset = mysqlnd_find_charset_nr(greet_packet->charset_no); - if (!conn->greet_charset) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "Server sent charset (%d) unknown to the client. Please, report to the developers", greet_packet->charset_no); - SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, - "Server sent charset unknown to the client. Please, report to the developers"); - goto err; - } - /* we allow load data local infile by default */ - mysql_flags |= MYSQLND_CAPABILITIES; - - if (db) { - mysql_flags |= CLIENT_CONNECT_WITH_DB; - } - - if (PG(open_basedir) && strlen(PG(open_basedir))) { - mysql_flags ^= CLIENT_LOCAL_FILES; - } - -#ifndef MYSQLND_COMPRESSION_ENABLED - if (mysql_flags & CLIENT_COMPRESS) { - mysql_flags &= ~CLIENT_COMPRESS; - } -#else - if (conn->net->options.flags & MYSQLND_NET_FLAG_USE_COMPRESSION) { - mysql_flags |= CLIENT_COMPRESS; - } -#endif -#ifndef MYSQLND_SSL_SUPPORTED - if (mysql_flags & CLIENT_SSL) { - mysql_flags &= ~CLIENT_SSL; - } -#else - if (conn->net->options.ssl_key || conn->net->options.ssl_cert || - conn->net->options.ssl_ca || conn->net->options.ssl_capath || conn->net->options.ssl_cipher) - { - mysql_flags |= CLIENT_SSL; - } -#endif - - if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len, - greet_packet, conn->options, mysql_flags TSRMLS_CC)) - { + if (FAIL == conn->m->connect_handshake(conn, host, user, passwd, passwd_len, db, db_len, mysql_flags TSRMLS_CC)) { goto err; } @@ -813,14 +953,14 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn, CONN_SET_STATE(conn, CONN_READY); if (saved_compression) { - conn->net->compressed = TRUE; + net->data->compressed = TRUE; } /* If a connect on a existing handle is performed and mysql_flags is passed which doesn't CLIENT_COMPRESS, then we need to overwrite the value which we set based on saved_compression. */ - conn->net->compressed = mysql_flags & CLIENT_COMPRESS? TRUE:FALSE; + net->data->compressed = mysql_flags & CLIENT_COMPRESS? TRUE:FALSE; conn->user = mnd_pestrdup(user, conn->persistent); conn->user_len = strlen(conn->user); @@ -882,46 +1022,17 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn, } conn->unix_socket_len = strlen(conn->unix_socket); } - conn->client_flag = mysql_flags; conn->max_packet_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE; /* todo: check if charset is available */ - conn->server_capabilities = greet_packet->server_capabilities; - conn->upsert_status->warning_count = 0; - conn->upsert_status->server_status = greet_packet->server_status; - conn->upsert_status->affected_rows = 0; SET_EMPTY_ERROR(*conn->error_info); mysqlnd_local_infile_default(conn); -#if MYSQLND_UNICODE - { - unsigned int as_unicode = 1; - conn->m->set_client_option(conn, MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE, (char *)&as_unicode TSRMLS_CC); - DBG_INF("unicode set"); - } -#endif - if (conn->options->init_commands) { - unsigned int current_command = 0; - for (; current_command < conn->options->num_commands; ++current_command) { - const char * const command = conn->options->init_commands[current_command]; - if (command) { - MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_EXECUTED_COUNT); - if (PASS != conn->m->query(conn, command, strlen(command) TSRMLS_CC)) { - MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_INIT_COMMAND_FAILED_COUNT); - goto err; - } - if (conn->last_query_type == QUERY_SELECT) { - MYSQLND_RES * result = conn->m->use_result(conn TSRMLS_CC); - if (result) { - result->m.free_result(result, TRUE TSRMLS_CC); - } - } - } - } + if (FAIL == conn->m->execute_init_commands(conn TSRMLS_CC)) { + goto err; } - MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats, STAT_CONNECT_SUCCESS, 1, STAT_OPENED_CONNECTIONS, 1); if (reconnect) { MYSQLND_INC_GLOBAL_STATISTIC(STAT_RECONNECT); @@ -932,13 +1043,10 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn, DBG_INF_FMT("connection_id=%llu", conn->thread_id); - PACKET_FREE(greet_packet); - conn->m->local_tx_end(conn, this_func, PASS TSRMLS_CC); DBG_RETURN(PASS); } err: - PACKET_FREE(greet_packet); DBG_ERR_FMT("[%u] %.128s (trying to connect via %s)", conn->error_info->error_no, conn->error_info->error, conn->scheme); if (!conn->error_info->error_no) { @@ -1036,7 +1144,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, query)(MYSQLND_CONN_DATA * conn, const char * size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, query); enum_func_status ret = FAIL; DBG_ENTER("mysqlnd_conn_data::query"); - DBG_INF_FMT("conn=%llu query=%s", conn->thread_id, query); + DBG_INF_FMT("conn=%p conn=%llu query=%s", conn, conn->thread_id, query); if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) { if (PASS == conn->m->send_query(conn, query, query_len TSRMLS_CC) && @@ -1149,7 +1257,7 @@ static int mysqlnd_stream_array_to_fd_set(MYSQLND ** conn_array, fd_set * fds, p * when casting. It is only used here so that the buffered data warning * is not displayed. * */ - if (SUCCESS == php_stream_cast((*p)->data->net->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, + if (SUCCESS == php_stream_cast((*p)->data->net->data->m.get_stream((*p)->data->net TSRMLS_CC), PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1) && this_fd >= 0) { PHP_SAFE_FD_SET(this_fd, fds); @@ -1174,7 +1282,7 @@ static int mysqlnd_stream_array_from_fd_set(MYSQLND ** conn_array, fd_set * fds MYSQLND **fwd = conn_array, **bckwd = conn_array; while (*fwd) { - if (SUCCESS == php_stream_cast((*fwd)->data->net->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, + if (SUCCESS == php_stream_cast((*fwd)->data->net->data->m.get_stream((*fwd)->data->net TSRMLS_CC), PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1) && this_fd >= 0) { if (PHP_SAFE_FD_ISSET(this_fd, fds)) { if (disproportion) { @@ -1220,13 +1328,12 @@ _mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long s DBG_RETURN(FAIL); } - *dont_poll = mysqlnd_stream_array_check_for_readiness(r_array TSRMLS_CC); - FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); if (r_array != NULL) { + *dont_poll = mysqlnd_stream_array_check_for_readiness(r_array TSRMLS_CC); set_count = mysqlnd_stream_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC); if (set_count > max_set_count) { max_set_count = set_count; @@ -1445,14 +1552,15 @@ MYSQLND_METHOD(mysqlnd_conn_data, ssl_set)(MYSQLND_CONN_DATA * const conn, const { size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, ssl_set); enum_func_status ret = FAIL; + MYSQLND_NET * net = conn->net; DBG_ENTER("mysqlnd_conn_data::ssl_set"); if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) { - ret = (PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_KEY, key TSRMLS_CC) && - PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CERT, cert TSRMLS_CC) && - PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CA, ca TSRMLS_CC) && - PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CAPATH, capath TSRMLS_CC) && - PASS == conn->net->m.set_client_option(conn->net, MYSQLND_OPT_SSL_CIPHER, cipher TSRMLS_CC)) ? PASS : FAIL; + ret = (PASS == net->data->m.set_client_option(net, MYSQLND_OPT_SSL_KEY, key TSRMLS_CC) && + PASS == net->data->m.set_client_option(net, MYSQLND_OPT_SSL_CERT, cert TSRMLS_CC) && + PASS == net->data->m.set_client_option(net, MYSQLND_OPT_SSL_CA, ca TSRMLS_CC) && + PASS == net->data->m.set_client_option(net, MYSQLND_OPT_SSL_CAPATH, capath TSRMLS_CC) && + PASS == net->data->m.set_client_option(net, MYSQLND_OPT_SSL_CIPHER, cipher TSRMLS_CC)) ? PASS : FAIL; conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); } @@ -1627,6 +1735,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, kill)(MYSQLND_CONN_DATA * conn, unsigned int p SET_ERROR_AFF_ROWS(conn); } else if (PASS == (ret = conn->m->simple_command(conn, COM_PROCESS_KILL, buff, 4, PROT_LAST, FALSE, TRUE TSRMLS_CC))) { CONN_SET_STATE(conn, CONN_QUIT_SENT); + conn->m->send_close(conn TSRMLS_CC); } conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); @@ -1724,10 +1833,11 @@ static enum_func_status MYSQLND_METHOD(mysqlnd_conn_data, send_close)(MYSQLND_CONN_DATA * const conn TSRMLS_DC) { enum_func_status ret = PASS; + MYSQLND_NET * net = conn->net; + php_stream * net_stream = net->data->m.get_stream(net TSRMLS_CC); DBG_ENTER("mysqlnd_send_close"); - DBG_INF_FMT("conn=%llu conn->net->stream->abstract=%p", - conn->thread_id, conn->net->stream? conn->net->stream->abstract:NULL); + DBG_INF_FMT("conn=%llu net->data->stream->abstract=%p", conn->thread_id, net_stream? net_stream->abstract:NULL); if (CONN_GET_STATE(conn) >= CONN_READY) { MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_CONNECTIONS); @@ -1738,10 +1848,11 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_close)(MYSQLND_CONN_DATA * const conn TSR switch (CONN_GET_STATE(conn)) { case CONN_READY: DBG_INF("Connection clean, sending COM_QUIT"); - if (conn->net->stream) { + if (net_stream) { ret = conn->m->simple_command(conn, COM_QUIT, NULL, 0, PROT_LAST, TRUE, TRUE TSRMLS_CC); + net->data->m.close_stream(net, conn->stats, conn->error_info TSRMLS_CC); } - /* Do nothing */ + CONN_SET_STATE(conn, CONN_QUIT_SENT); break; case CONN_SENDING_LOAD_DATA: /* @@ -1757,6 +1868,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_close)(MYSQLND_CONN_DATA * const conn TSR Do nothing, the connection will be brutally closed and the server will catch it and free close from its side. */ + /* Fall-through */ case CONN_ALLOCED: /* Allocated but not connected or there was failure when trying @@ -1764,15 +1876,13 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_close)(MYSQLND_CONN_DATA * const conn TSR Fall-through */ + CONN_SET_STATE(conn, CONN_QUIT_SENT); + /* Fall-through */ case CONN_QUIT_SENT: /* The user has killed its own connection */ + net->data->m.close_stream(net, conn->stats, conn->error_info TSRMLS_CC); break; } - /* - We hold one reference, and every other object which needs the - connection does increase it by 1. - */ - CONN_SET_STATE(conn, CONN_QUIT_SENT); DBG_RETURN(ret); } @@ -1814,7 +1924,7 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, free_reference)(MYSQLND_CONN_DATA * co /* {{{ mysqlnd_conn_data::get_state */ static enum mysqlnd_connection_state -MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_state)(MYSQLND_CONN_DATA * const conn TSRMLS_DC) +MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_state)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC) { DBG_ENTER("mysqlnd_conn_data::get_state"); DBG_RETURN(conn->state); @@ -2012,6 +2122,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, next_result)(MYSQLND_CONN_DATA * const conn TS DBG_ERR_FMT("Serious error. %s::%u", __FILE__, __LINE__); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Serious error. PID=%d", getpid()); CONN_SET_STATE(conn, CONN_QUIT_SENT); + conn->m->send_close(conn TSRMLS_CC); } else { DBG_INF_FMT("Error from the server : (%u) %s", conn->error_info->error_no, conn->error_info->error); } @@ -2091,13 +2202,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, change_user)(MYSQLND_CONN_DATA * const conn, TSRMLS_DC) { size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, change_user); - /* - User could be max 16 * 3 (utf8), pass is 20 usually, db is up to 64*3 - Stack space is not that expensive, so use a bit more to be protected against - buffer overflows. - */ enum_func_status ret = FAIL; - zend_bool local_tx_started = FALSE; DBG_ENTER("mysqlnd_conn_data::change_user"); DBG_INF_FMT("conn=%llu user=%s passwd=%s db=%s silent=%u", @@ -2106,7 +2211,6 @@ MYSQLND_METHOD(mysqlnd_conn_data, change_user)(MYSQLND_CONN_DATA * const conn, if (PASS != conn->m->local_tx_start(conn, this_func TSRMLS_CC)) { goto end; } - local_tx_started = TRUE; SET_EMPTY_ERROR(*conn->error_info); SET_ERROR_AFF_ROWS(conn); @@ -2119,122 +2223,20 @@ MYSQLND_METHOD(mysqlnd_conn_data, change_user)(MYSQLND_CONN_DATA * const conn, } if (!db) { db = ""; - } - - { - zend_bool first_call = TRUE; - char * switch_to_auth_protocol = NULL; - size_t switch_to_auth_protocol_len = 0; - char * requested_protocol = NULL; - zend_uchar * plugin_data; - size_t plugin_data_len; - - plugin_data_len = conn->auth_plugin_data_len; - plugin_data = mnd_emalloc(plugin_data_len); - if (!plugin_data) { - ret = FAIL; - goto end; - } - memcpy(plugin_data, conn->auth_plugin_data, plugin_data_len); - - requested_protocol = mnd_pestrdup(conn->options->auth_protocol? conn->options->auth_protocol:"mysql_native_password", FALSE); - if (!requested_protocol) { - ret = FAIL; - goto end; - } - - do { - struct st_mysqlnd_authentication_plugin * auth_plugin; - { - char * plugin_name = NULL; - - mnd_sprintf(&plugin_name, 0, "auth_plugin_%s", requested_protocol); - DBG_INF_FMT("looking for %s auth plugin", plugin_name); - auth_plugin = mysqlnd_plugin_find(plugin_name); - mnd_sprintf_free(plugin_name); - - if (!auth_plugin) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "The server requested authentication method unknown to the client [%s]", requested_protocol); - SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "The server requested authentication method umknown to the client"); - break; - } - } - DBG_INF("plugin found"); - - { - zend_uchar * switch_to_auth_protocol_data = NULL; - size_t switch_to_auth_protocol_data_len = 0; - zend_uchar * scrambled_data = NULL; - size_t scrambled_data_len = 0; - - switch_to_auth_protocol = NULL; - switch_to_auth_protocol_len = 0; - - if (conn->auth_plugin_data) { - mnd_pefree(conn->auth_plugin_data, conn->persistent); - conn->auth_plugin_data = NULL; - } - conn->auth_plugin_data_len = plugin_data_len; - conn->auth_plugin_data = mnd_pemalloc(conn->auth_plugin_data_len, conn->persistent); - if (!conn->auth_plugin_data) { - SET_OOM_ERROR(*conn->error_info); - ret = FAIL; - goto end; - } - memcpy(conn->auth_plugin_data, plugin_data, plugin_data_len); - - DBG_INF_FMT("salt=[%*.s]", plugin_data_len - 1, plugin_data); - - /* The data should be allocated with malloc() */ - scrambled_data = - auth_plugin->methods.get_auth_data(NULL, &scrambled_data_len, conn, user, passwd, passwd_len, - plugin_data, plugin_data_len, 0, conn->server_capabilities TSRMLS_CC); - - - ret = mysqlnd_auth_change_user(conn, user, strlen(user), passwd, passwd_len, db, strlen(db), silent, - first_call, - requested_protocol, - scrambled_data, scrambled_data_len, - &switch_to_auth_protocol, &switch_to_auth_protocol_len, - &switch_to_auth_protocol_data, &switch_to_auth_protocol_data_len - TSRMLS_CC); + } - first_call = FALSE; - free(scrambled_data); + /* XXX: passwords that have \0 inside work during auth, but in this case won't work with change user */ + ret = mysqlnd_run_authentication(conn, user, passwd, strlen(passwd), db, strlen(db), + conn->auth_plugin_data, conn->auth_plugin_data_len, conn->options->auth_protocol, + 0 /*charset not used*/, conn->options, conn->server_capabilities, silent, TRUE/*is_change*/ TSRMLS_CC); - DBG_INF_FMT("switch_to_auth_protocol=%s", switch_to_auth_protocol? switch_to_auth_protocol:"n/a"); - if (requested_protocol) { - mnd_efree(requested_protocol); - } - requested_protocol = switch_to_auth_protocol; - - if (plugin_data) { - mnd_efree(plugin_data); - } - plugin_data_len = switch_to_auth_protocol_data_len; - plugin_data = switch_to_auth_protocol_data; - } - DBG_INF_FMT("conn->error_info->error_no = %d", conn->error_info->error_no); - } while (ret == FAIL && conn->error_info->error_no == 0 && switch_to_auth_protocol != NULL); - if (plugin_data) { - mnd_efree(plugin_data); - } - if (ret == PASS) { - conn->m->set_client_option(conn, MYSQLND_OPT_AUTH_PROTOCOL, requested_protocol TSRMLS_CC); - } - if (requested_protocol) { - mnd_efree(requested_protocol); - } - } /* Here we should close all statements. Unbuffered queries should not be a problem as we won't allow sending COM_CHANGE_USER. */ + conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); end: - if (TRUE == local_tx_started) { - conn->m->local_tx_end(conn, this_func, ret TSRMLS_CC); - } DBG_INF(ret == PASS? "PASS":"FAIL"); DBG_RETURN(ret); } @@ -2271,13 +2273,9 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const c case MYSQL_OPT_CONNECT_TIMEOUT: case MYSQLND_OPT_NET_CMD_BUFFER_SIZE: case MYSQLND_OPT_NET_READ_BUFFER_SIZE: - ret = conn->net->m.set_client_option(conn->net, option, value TSRMLS_CC); - break; -#if MYSQLND_UNICODE - case MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE: - conn->options->numeric_and_datetime_as_unicode = *(unsigned int*) value; + case MYSQL_SERVER_PUBLIC_KEY: + ret = conn->net->data->m.set_client_option(conn->net, option, value TSRMLS_CC); break; -#endif #ifdef MYSQLND_STRING_TO_INT_CONVERSION case MYSQLND_OPT_INT_AND_FLOAT_NATIVE: conn->options->int_and_float_native = *(unsigned int*) value; @@ -2438,7 +2436,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, store_result)(MYSQLND_CONN_DATA * const conn T MYSQLND_RES * result = NULL; DBG_ENTER("mysqlnd_conn_data::store_result"); - DBG_INF_FMT("conn=%llu", conn->thread_id); + DBG_INF_FMT("conn=%llu conn=%p", conn->thread_id, conn); if (PASS == conn->m->local_tx_start(conn, this_func TSRMLS_CC)) { do { @@ -2650,7 +2648,12 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data) MYSQLND_METHOD(mysqlnd_conn_data, tx_commit), MYSQLND_METHOD(mysqlnd_conn_data, tx_rollback), MYSQLND_METHOD(mysqlnd_conn_data, local_tx_start), - MYSQLND_METHOD(mysqlnd_conn_data, local_tx_end) + MYSQLND_METHOD(mysqlnd_conn_data, local_tx_end), + MYSQLND_METHOD(mysqlnd_conn_data, execute_init_commands), + MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags), + MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake), + MYSQLND_METHOD(mysqlnd_conn_data, simple_command_send_request), + MYSQLND_METHOD(mysqlnd_conn_data, fetch_auth_plugin_by_name) MYSQLND_CLASS_METHODS_END; diff --git a/ext/mysqlnd/mysqlnd.h b/ext/mysqlnd/mysqlnd.h index b0b3b15c69..b0db48f5f7 100644 --- a/ext/mysqlnd/mysqlnd.h +++ b/ext/mysqlnd/mysqlnd.h @@ -22,10 +22,10 @@ #ifndef MYSQLND_H #define MYSQLND_H -#define MYSQLND_VERSION "mysqlnd 5.0.10 - 20111026 - $Id$" -#define MYSQLND_VERSION_ID 50010 +#define MYSQLND_VERSION "mysqlnd 5.0.11-dev - 20120503 - $Id$" +#define MYSQLND_VERSION_ID 50011 -#define MYSQLND_PLUGIN_API_VERSION 1 +#define MYSQLND_PLUGIN_API_VERSION 2 #define MYSQLND_STRING_TO_INT_CONVERSION /* @@ -262,8 +262,10 @@ PHPAPI void _mysqlnd_get_client_stats(zval *return_value TSRMLS_DC ZEND_FILE_L ZEND_BEGIN_MODULE_GLOBALS(mysqlnd) zend_bool collect_statistics; zend_bool collect_memory_statistics; - char* debug; /* The actual string */ - MYSQLND_DEBUG *dbg; /* The DBG object */ + char * debug; /* The actual string */ + char * trace_alloc_settings; /* The actual string */ + MYSQLND_DEBUG * dbg; /* The DBG object for standard tracing */ + MYSQLND_DEBUG * trace_alloc; /* The DBG object for allocation tracing */ long net_cmd_buffer_size; long net_read_buffer_size; long log_mask; @@ -275,6 +277,7 @@ ZEND_BEGIN_MODULE_GLOBALS(mysqlnd) long debug_malloc_fail_threshold; long debug_calloc_fail_threshold; long debug_realloc_fail_threshold; + char * sha256_server_public_key; ZEND_END_MODULE_GLOBALS(mysqlnd) PHPAPI ZEND_EXTERN_MODULE_GLOBALS(mysqlnd) diff --git a/ext/mysqlnd/mysqlnd_alloc.c b/ext/mysqlnd/mysqlnd_alloc.c index 06e979a6e1..e681d33856 100644 --- a/ext/mysqlnd/mysqlnd_alloc.c +++ b/ext/mysqlnd/mysqlnd_alloc.c @@ -65,8 +65,8 @@ const char * mysqlnd_debug_std_no_trace_funcs[] = #if ZEND_DEBUG #else -#define __zend_filename "/unknown/unknown" -#define __zend_lineno 0 +#define __zend_orig_filename "/unknown/unknown" +#define __zend_orig_lineno 0 #endif #define REAL_SIZE(s) (collect_memory_statistics? (s) + sizeof(size_t) : (s)) @@ -81,15 +81,17 @@ void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D) #if PHP_DEBUG long * threshold = &MYSQLND_G(debug_emalloc_fail_threshold); #endif - DBG_ENTER(mysqlnd_emalloc_name); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_emalloc_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno); #if PHP_DEBUG /* -1 is also "true" */ if (*threshold) { #endif - ret = emalloc(REAL_SIZE(size)); + ret = _emalloc(REAL_SIZE(size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC); #if PHP_DEBUG --*threshold; } else if (*threshold == 0) { @@ -97,13 +99,13 @@ void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D) } #endif - DBG_INF_FMT("size=%lu ptr=%p", size, ret); + TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret); if (ret && collect_memory_statistics) { *(size_t *) ret = size; MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMOUNT, size); } - DBG_RETURN(FAKE_PTR(ret)); + TRACE_ALLOC_RETURN(FAKE_PTR(ret)); } /* }}} */ @@ -116,14 +118,16 @@ void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D) #if PHP_DEBUG long * threshold = persistent? &MYSQLND_G(debug_malloc_fail_threshold):&MYSQLND_G(debug_emalloc_fail_threshold); #endif - DBG_ENTER(mysqlnd_pemalloc_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_pemalloc_name); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d persistent=%u", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno, persistent); #if PHP_DEBUG /* -1 is also "true" */ if (*threshold) { #endif - ret = pemalloc(REAL_SIZE(size), persistent); + ret = (persistent) ? __zend_malloc(REAL_SIZE(size)) : _emalloc(REAL_SIZE(size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC); #if PHP_DEBUG --*threshold; } else if (*threshold == 0) { @@ -131,7 +135,7 @@ void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D) } #endif - DBG_INF_FMT("size=%lu ptr=%p persistent=%u", size, ret, persistent); + TRACE_ALLOC_INF_FMT("size=%lu ptr=%p persistent=%u", size, ret, persistent); if (ret && collect_memory_statistics) { enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_MALLOC_COUNT:STAT_MEM_EMALLOC_COUNT; @@ -140,7 +144,7 @@ void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D) MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size); } - DBG_RETURN(FAKE_PTR(ret)); + TRACE_ALLOC_RETURN(FAKE_PTR(ret)); } /* }}} */ @@ -153,15 +157,17 @@ void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D) #if PHP_DEBUG long * threshold = &MYSQLND_G(debug_ecalloc_fail_threshold); #endif - DBG_ENTER(mysqlnd_ecalloc_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); - DBG_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC)); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_ecalloc_name); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno); + TRACE_ALLOC_INF_FMT("before: %lu", zend_memory_usage(FALSE TSRMLS_CC)); #if PHP_DEBUG /* -1 is also "true" */ if (*threshold) { #endif - ret = ecalloc(nmemb, REAL_SIZE(size)); + ret = _ecalloc(nmemb, REAL_SIZE(size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC); #if PHP_DEBUG --*threshold; } else if (*threshold == 0) { @@ -169,13 +175,13 @@ void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D) } #endif - DBG_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC)); - DBG_INF_FMT("size=%lu ptr=%p", size, ret); + TRACE_ALLOC_INF_FMT("after : %lu", zend_memory_usage(FALSE TSRMLS_CC)); + TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret); if (ret && collect_memory_statistics) { *(size_t *) ret = size; MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_ECALLOC_COUNT, 1, STAT_MEM_ECALLOC_AMOUNT, size); } - DBG_RETURN(FAKE_PTR(ret)); + TRACE_ALLOC_RETURN(FAKE_PTR(ret)); } /* }}} */ @@ -188,14 +194,16 @@ void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent M #if PHP_DEBUG long * threshold = persistent? &MYSQLND_G(debug_calloc_fail_threshold):&MYSQLND_G(debug_ecalloc_fail_threshold); #endif - DBG_ENTER(mysqlnd_pecalloc_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_pecalloc_name); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d persistent=%u", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno, persistent); #if PHP_DEBUG /* -1 is also "true" */ if (*threshold) { #endif - ret = pecalloc(nmemb, REAL_SIZE(size), persistent); + ret = (persistent) ? __zend_calloc(nmemb, REAL_SIZE(size)) : _ecalloc(nmemb, REAL_SIZE(size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC); #if PHP_DEBUG --*threshold; } else if (*threshold == 0) { @@ -203,7 +211,7 @@ void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent M } #endif - DBG_INF_FMT("size=%lu ptr=%p", size, ret); + TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret); if (ret && collect_memory_statistics) { enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_CALLOC_COUNT:STAT_MEM_ECALLOC_COUNT; @@ -212,7 +220,7 @@ void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent M MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size); } - DBG_RETURN(FAKE_PTR(ret)); + TRACE_ALLOC_RETURN(FAKE_PTR(ret)); } /* }}} */ @@ -226,15 +234,17 @@ void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D) #if PHP_DEBUG long * threshold = &MYSQLND_G(debug_erealloc_fail_threshold); #endif - DBG_ENTER(mysqlnd_erealloc_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); - DBG_INF_FMT("ptr=%p old_size=%lu, new_size=%lu", ptr, old_size, new_size); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_erealloc_name); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno); + TRACE_ALLOC_INF_FMT("ptr=%p old_size=%lu, new_size=%lu", ptr, old_size, new_size); #if PHP_DEBUG /* -1 is also "true" */ if (*threshold) { #endif - ret = erealloc(REAL_PTR(ptr), REAL_SIZE(new_size)); + ret = _erealloc(REAL_PTR(ptr), REAL_SIZE(new_size), 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC); #if PHP_DEBUG --*threshold; } else if (*threshold == 0) { @@ -242,12 +252,12 @@ void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D) } #endif - DBG_INF_FMT("new_ptr=%p", (char*)ret); + TRACE_ALLOC_INF_FMT("new_ptr=%p", (char*)ret); if (ret && collect_memory_statistics) { *(size_t *) ret = new_size; MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EREALLOC_COUNT, 1, STAT_MEM_EREALLOC_AMOUNT, new_size); } - DBG_RETURN(FAKE_PTR(ret)); + TRACE_ALLOC_RETURN(FAKE_PTR(ret)); } /* }}} */ @@ -261,9 +271,11 @@ void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQL #if PHP_DEBUG long * threshold = persistent? &MYSQLND_G(debug_realloc_fail_threshold):&MYSQLND_G(debug_erealloc_fail_threshold); #endif - DBG_ENTER(mysqlnd_perealloc_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); - DBG_INF_FMT("ptr=%p old_size=%lu new_size=%lu persistent=%u", ptr, old_size, new_size, persistent); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_perealloc_name); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno); + TRACE_ALLOC_INF_FMT("ptr=%p old_size=%lu new_size=%lu persistent=%u", ptr, old_size, new_size, persistent); #if PHP_DEBUG /* -1 is also "true" */ @@ -277,7 +289,7 @@ void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQL } #endif - DBG_INF_FMT("new_ptr=%p", (char*)ret); + TRACE_ALLOC_INF_FMT("new_ptr=%p", (char*)ret); if (ret && collect_memory_statistics) { enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT; @@ -285,7 +297,7 @@ void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQL *(size_t *) ret = new_size; MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, new_size); } - DBG_RETURN(FAKE_PTR(ret)); + TRACE_ALLOC_RETURN(FAKE_PTR(ret)); } /* }}} */ @@ -295,22 +307,24 @@ void _mysqlnd_efree(void *ptr MYSQLND_MEM_D) { size_t free_amount = 0; zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics); - DBG_ENTER(mysqlnd_efree_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); - DBG_INF_FMT("ptr=%p", ptr); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_efree_name); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno); + TRACE_ALLOC_INF_FMT("ptr=%p", ptr); if (ptr) { if (collect_memory_statistics) { free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t)); - DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount); + TRACE_ALLOC_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount); } - efree(REAL_PTR(ptr)); + _efree(REAL_PTR(ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } if (collect_memory_statistics) { MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EFREE_COUNT, 1, STAT_MEM_EFREE_AMOUNT, free_amount); } - DBG_VOID_RETURN; + TRACE_ALLOC_VOID_RETURN; } /* }}} */ @@ -320,24 +334,27 @@ void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D) { size_t free_amount = 0; zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics); - DBG_ENTER(mysqlnd_pefree_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); - DBG_INF_FMT("ptr=%p persistent=%u", ptr, persistent); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_pefree_name); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno); + TRACE_ALLOC_INF_FMT("ptr=%p persistent=%u", ptr, persistent); if (ptr) { if (collect_memory_statistics) { free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t)); - DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount); + TRACE_ALLOC_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount); } - pefree(REAL_PTR(ptr), persistent); + (persistent) ? free(REAL_PTR(ptr)) : _efree(REAL_PTR(ptr) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC); } if (collect_memory_statistics) { MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(persistent? STAT_MEM_FREE_COUNT:STAT_MEM_EFREE_COUNT, 1, persistent? STAT_MEM_FREE_AMOUNT:STAT_MEM_EFREE_AMOUNT, free_amount); } - DBG_VOID_RETURN; + TRACE_ALLOC_VOID_RETURN; } +/* }}} */ /* {{{ _mysqlnd_malloc */ @@ -348,8 +365,10 @@ void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D) #if PHP_DEBUG long * threshold = &MYSQLND_G(debug_malloc_fail_threshold); #endif - DBG_ENTER(mysqlnd_malloc_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_malloc_name); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno); #if PHP_DEBUG /* -1 is also "true" */ @@ -363,12 +382,12 @@ void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D) } #endif - DBG_INF_FMT("size=%lu ptr=%p", size, ret); + TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret); if (ret && collect_memory_statistics) { *(size_t *) ret = size; MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_MALLOC_COUNT, 1, STAT_MEM_MALLOC_AMOUNT, size); } - DBG_RETURN(FAKE_PTR(ret)); + TRACE_ALLOC_RETURN(FAKE_PTR(ret)); } /* }}} */ @@ -381,8 +400,10 @@ void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D) #if PHP_DEBUG long * threshold = &MYSQLND_G(debug_calloc_fail_threshold); #endif - DBG_ENTER(mysqlnd_calloc_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_calloc_name); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno); #if PHP_DEBUG /* -1 is also "true" */ @@ -396,12 +417,12 @@ void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D) } #endif - DBG_INF_FMT("size=%lu ptr=%p", size, ret); + TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret); if (ret && collect_memory_statistics) { *(size_t *) ret = size; MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_CALLOC_COUNT, 1, STAT_MEM_CALLOC_AMOUNT, size); } - DBG_RETURN(FAKE_PTR(ret)); + TRACE_ALLOC_RETURN(FAKE_PTR(ret)); } /* }}} */ @@ -414,10 +435,12 @@ void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D) #if PHP_DEBUG long * threshold = &MYSQLND_G(debug_realloc_fail_threshold); #endif - DBG_ENTER(mysqlnd_realloc_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); - DBG_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr); - DBG_INF_FMT("before: %lu", zend_memory_usage(TRUE TSRMLS_CC)); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_realloc_name); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno); + TRACE_ALLOC_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr); + TRACE_ALLOC_INF_FMT("before: %lu", zend_memory_usage(TRUE TSRMLS_CC)); #if PHP_DEBUG /* -1 is also "true" */ @@ -431,13 +454,13 @@ void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D) } #endif - DBG_INF_FMT("new_ptr=%p", (char*)ret); + TRACE_ALLOC_INF_FMT("new_ptr=%p", (char*)ret); if (ret && collect_memory_statistics) { *(size_t *) ret = new_size; MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_REALLOC_COUNT, 1, STAT_MEM_REALLOC_AMOUNT, new_size); } - DBG_RETURN(FAKE_PTR(ret)); + TRACE_ALLOC_RETURN(FAKE_PTR(ret)); } /* }}} */ @@ -447,14 +470,16 @@ void _mysqlnd_free(void *ptr MYSQLND_MEM_D) { size_t free_amount = 0; zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics); - DBG_ENTER(mysqlnd_free_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); - DBG_INF_FMT("ptr=%p", ptr); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_free_name); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno); + TRACE_ALLOC_INF_FMT("ptr=%p", ptr); if (ptr) { if (collect_memory_statistics) { free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t)); - DBG_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount); + TRACE_ALLOC_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount); } free(REAL_PTR(ptr)); } @@ -462,7 +487,7 @@ void _mysqlnd_free(void *ptr MYSQLND_MEM_D) if (collect_memory_statistics) { MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_FREE_COUNT, 1, STAT_MEM_FREE_AMOUNT, free_amount); } - DBG_VOID_RETURN; + TRACE_ALLOC_VOID_RETURN; } /* }}} */ @@ -476,11 +501,13 @@ char * _mysqlnd_pestrndup(const char * const ptr, size_t length, zend_bool persi { char * ret; zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics); - DBG_ENTER(mysqlnd_pestrndup_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); - DBG_INF_FMT("ptr=%p", ptr); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_pestrndup_name); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno); + TRACE_ALLOC_INF_FMT("ptr=%p", ptr); - ret = pemalloc(REAL_SIZE(length) + 1, persistent); + ret = (persistent) ? __zend_malloc(REAL_SIZE(length + 1)) : _emalloc(REAL_SIZE(length + 1) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC); { size_t l = length; char * p = (char *) ptr; @@ -496,7 +523,7 @@ char * _mysqlnd_pestrndup(const char * const ptr, size_t length, zend_bool persi MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRNDUP_COUNT : STAT_MEM_ESTRNDUP_COUNT); } - DBG_RETURN(FAKE_PTR(ret)); + TRACE_ALLOC_RETURN(FAKE_PTR(ret)); } /* }}} */ @@ -508,14 +535,16 @@ char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_ME smart_str tmp_str = {0, 0, 0}; const char * p = ptr; zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics); - DBG_ENTER(mysqlnd_pestrdup_name); - DBG_INF_FMT("file=%-15s line=%4d", strrchr(__zend_filename, PHP_DIR_SEPARATOR) + 1, __zend_lineno); - DBG_INF_FMT("ptr=%p", ptr); + char * fn = NULL; + TRACE_ALLOC_ENTER(mysqlnd_pestrdup_name); + TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", + (fn = strrchr(__zend_orig_filename, PHP_DIR_SEPARATOR))? fn + 1:__zend_orig_filename, __zend_orig_lineno); + TRACE_ALLOC_INF_FMT("ptr=%p", ptr); do { smart_str_appendc(&tmp_str, *p); } while (*p++); - ret = pemalloc(tmp_str.len + sizeof(size_t), persistent); + ret = (persistent) ? __zend_malloc(tmp_str.len + sizeof(size_t)) : _emalloc(REAL_SIZE(tmp_str.len + sizeof(size_t)) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC); memcpy(FAKE_PTR(ret), tmp_str.c, tmp_str.len); if (ret && collect_memory_statistics) { @@ -524,7 +553,7 @@ char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_ME } smart_str_free(&tmp_str); - DBG_RETURN(FAKE_PTR(ret)); + TRACE_ALLOC_RETURN(FAKE_PTR(ret)); } /* }}} */ @@ -549,7 +578,7 @@ PHPAPI void _mysqlnd_sprintf_free(char * p) } /* }}} */ - +/* {{{ _mysqlnd_vsprintf */ PHPAPI int _mysqlnd_vsprintf(char ** pbuf, size_t max_len, const char * format, va_list ap) { return vspprintf(pbuf, max_len, format, ap); diff --git a/ext/mysqlnd/mysqlnd_alloc.h b/ext/mysqlnd/mysqlnd_alloc.h index 673d4f6dae..8d0e3bfacc 100644 --- a/ext/mysqlnd/mysqlnd_alloc.h +++ b/ext/mysqlnd/mysqlnd_alloc.h @@ -26,8 +26,8 @@ extern const char * mysqlnd_debug_std_no_trace_funcs[]; -#define MYSQLND_MEM_D TSRMLS_DC ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC -#define MYSQLND_MEM_C TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC +#define MYSQLND_MEM_D TSRMLS_DC ZEND_FILE_LINE_ORIG_DC +#define MYSQLND_MEM_C TSRMLS_CC ZEND_FILE_LINE_CC struct st_mysqlnd_allocator_methods { diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c index 10c932a968..cdbdf6d7ed 100644 --- a/ext/mysqlnd/mysqlnd_auth.c +++ b/ext/mysqlnd/mysqlnd_auth.c @@ -88,11 +88,7 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn, if (options->charset_name && (charset = mysqlnd_find_charset_name(options->charset_name))) { auth_packet->charset_no = charset->nr; } else { -#if MYSQLND_UNICODE - auth_packet->charset_no = 200;/* utf8 - swedish collation, check mysqlnd_charset.c */ -#else auth_packet->charset_no = server_charset_no; -#endif } auth_packet->send_auth_data = TRUE; @@ -360,7 +356,9 @@ mysqlnd_native_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self size_t * auth_data_len, MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd, const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len, - const MYSQLND_OPTIONS * const options, unsigned long mysql_flags + const MYSQLND_OPTIONS * const options, + const MYSQLND_NET_OPTIONS * const net_options, + unsigned long mysql_flags TSRMLS_DC) { zend_uchar * ret = NULL; @@ -418,7 +416,9 @@ mysqlnd_pam_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self, size_t * auth_data_len, MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd, const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len, - const MYSQLND_OPTIONS * const options, unsigned long mysql_flags + const MYSQLND_OPTIONS * const options, + const MYSQLND_NET_OPTIONS * const net_options, + unsigned long mysql_flags TSRMLS_DC) { zend_uchar * ret = NULL; @@ -442,7 +442,7 @@ static struct st_mysqlnd_authentication_plugin mysqlnd_pam_authentication_plugin MYSQLND_VERSION_ID, MYSQLND_VERSION, "PHP License 3.01", - "Andrey Hristov <andrey@mysql.com>, Ulf Wendel <uwendel@mysql.com>, Georg Richter <georg@mysql.com>", + "Andrey Hristov <andrey@php.net>, Ulf Wendel <uw@php.net>, Georg Richter <georg@php.net>", { NULL, /* no statistics , will be filled later if there are some */ NULL, /* no statistics */ @@ -457,12 +457,202 @@ static struct st_mysqlnd_authentication_plugin mysqlnd_pam_authentication_plugin }; +/******************************************* SHA256 Password ***********************************/ +#ifdef MYSQLND_HAVE_SSL +static void +mysqlnd_xor_string(char * dst, const size_t dst_len, const char * xor_str, const size_t xor_str_len) +{ + unsigned int i; + for (i = 0; i <= dst_len; ++i) { + dst[i] ^= xor_str[i % xor_str_len]; + } +} + + +#include <openssl/rsa.h> +#include <openssl/pem.h> +#include <openssl/err.h> + + +/* {{{ mysqlnd_sha256_get_rsa_key */ +static RSA * +mysqlnd_sha256_get_rsa_key(MYSQLND_CONN_DATA * conn, + const MYSQLND_OPTIONS * const options, + const MYSQLND_NET_OPTIONS * const net_options + TSRMLS_DC) +{ + RSA * ret = NULL; + int len; + const char * fname = (net_options->sha256_server_public_key && net_options->sha256_server_public_key[0] != '\0')? + net_options->sha256_server_public_key: + MYSQLND_G(sha256_server_public_key); + php_stream * stream; + DBG_ENTER("mysqlnd_sha256_get_rsa_key"); + DBG_INF_FMT("options_s256_pk=[%s] MYSQLND_G(sha256_server_public_key)=[%s]", + net_options->sha256_server_public_key? net_options->sha256_server_public_key:"n/a", + MYSQLND_G(sha256_server_public_key)? MYSQLND_G(sha256_server_public_key):"n/a"); + if (!fname || fname[0] == '\0') { + MYSQLND_PACKET_SHA256_PK_REQUEST * pk_req_packet = NULL; + MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE * pk_resp_packet = NULL; + + do { + DBG_INF("requesting the public key from the server"); + pk_req_packet = conn->protocol->m.get_sha256_pk_request_packet(conn->protocol, FALSE TSRMLS_CC); + if (!pk_req_packet) { + SET_OOM_ERROR(*conn->error_info); + break; + } + pk_resp_packet = conn->protocol->m.get_sha256_pk_request_response_packet(conn->protocol, FALSE TSRMLS_CC); + if (!pk_resp_packet) { + SET_OOM_ERROR(*conn->error_info); + PACKET_FREE(pk_req_packet); + break; + } + + if (! PACKET_WRITE(pk_req_packet, conn)) { + DBG_ERR_FMT("Error while sending public key request packet"); + php_error(E_WARNING, "Error while sending public key request packet. PID=%d", getpid()); + CONN_SET_STATE(conn, CONN_QUIT_SENT); + break; + } + if (FAIL == PACKET_READ(pk_resp_packet, conn) || NULL == pk_resp_packet->public_key) { + DBG_ERR_FMT("Error while receiving public key"); + php_error(E_WARNING, "Error while receiving public key. PID=%d", getpid()); + CONN_SET_STATE(conn, CONN_QUIT_SENT); + break; + } + DBG_INF_FMT("Public key(%d):\n%s", pk_resp_packet->public_key_len, pk_resp_packet->public_key); + /* now extract the public key */ + { + BIO * bio = BIO_new_mem_buf(pk_resp_packet->public_key, pk_resp_packet->public_key_len); + ret = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); + BIO_free(bio); + } + } while (0); + PACKET_FREE(pk_req_packet); + PACKET_FREE(pk_resp_packet); + + DBG_INF_FMT("ret=%p", ret); + DBG_RETURN(ret); + + SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, + "sha256_server_public_key is not set for the connection or as mysqlnd.sha256_server_public_key"); + DBG_ERR("server_public_key is not set"); + DBG_RETURN(NULL); + } else { + char * key_str = NULL; + DBG_INF_FMT("Key in a file. [%s]", fname); + stream = php_stream_open_wrapper((char *) fname, "rb", REPORT_ERRORS, NULL); + + if (stream) { + if ((len = php_stream_copy_to_mem(stream, &key_str, PHP_STREAM_COPY_ALL, 0)) >= 0 ) { + BIO * bio = BIO_new_mem_buf(key_str, len); + ret = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL); + BIO_free(bio); + DBG_INF("Successfully loaded"); + } + if (key_str) { + DBG_INF_FMT("Public key:%*.s", len, key_str); + efree(key_str); + } + php_stream_free(stream, PHP_STREAM_FREE_CLOSE); + } + } + DBG_RETURN(ret); +} +/* }}} */ + + +/* {{{ mysqlnd_sha256_auth_get_auth_data */ +static zend_uchar * +mysqlnd_sha256_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self, + size_t * auth_data_len, + MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd, + const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len, + const MYSQLND_OPTIONS * const options, + const MYSQLND_NET_OPTIONS * const net_options, + unsigned long mysql_flags + TSRMLS_DC) +{ + RSA * server_public_key; + zend_uchar * ret = NULL; + DBG_ENTER("mysqlnd_sha256_auth_get_auth_data"); + DBG_INF_FMT("salt(%d)=[%.*s]", auth_plugin_data_len, auth_plugin_data_len, auth_plugin_data); + + + if (conn->net->data->ssl) { + DBG_INF("simple clear text under SSL"); + /* clear text under SSL */ + *auth_data_len = passwd_len; + ret = malloc(passwd_len); + memcpy(ret, passwd, passwd_len); + } else { + *auth_data_len = 0; + server_public_key = mysqlnd_sha256_get_rsa_key(conn, options, net_options TSRMLS_CC); + + if (server_public_key) { + int server_public_key_len; + char xor_str[passwd_len + 1]; + memcpy(xor_str, passwd, passwd_len); + xor_str[passwd_len] = '\0'; + mysqlnd_xor_string(xor_str, passwd_len, (char *) auth_plugin_data, auth_plugin_data_len); + + server_public_key_len = RSA_size(server_public_key); + /* + Because RSA_PKCS1_OAEP_PADDING is used there is a restriction on the passwd_len. + RSA_PKCS1_OAEP_PADDING is recommended for new applications. See more here: + http://www.openssl.org/docs/crypto/RSA_public_encrypt.html + */ + if ((size_t) server_public_key_len - 41 <= passwd_len) { + /* password message is to long */ + SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "password is too long"); + DBG_ERR("password is too long"); + DBG_RETURN(NULL); + } + + *auth_data_len = server_public_key_len; + ret = malloc(*auth_data_len); + RSA_public_encrypt(passwd_len + 1, (zend_uchar *) xor_str, ret, server_public_key, RSA_PKCS1_OAEP_PADDING); + } + } + + DBG_RETURN(ret); +} +/* }}} */ + + +static struct st_mysqlnd_authentication_plugin mysqlnd_sha256_authentication_plugin = +{ + { + MYSQLND_PLUGIN_API_VERSION, + "auth_plugin_sha256_password", + MYSQLND_VERSION_ID, + MYSQLND_VERSION, + "PHP License 3.01", + "Andrey Hristov <andrey@mysql.com>, Ulf Wendel <uwendel@mysql.com>", + { + NULL, /* no statistics , will be filled later if there are some */ + NULL, /* no statistics */ + }, + { + NULL /* plugin shutdown */ + } + }, + {/* methods */ + mysqlnd_sha256_auth_get_auth_data + } +}; +#endif + /* {{{ mysqlnd_register_builtin_authentication_plugins */ void mysqlnd_register_builtin_authentication_plugins(TSRMLS_D) { mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_native_auth_plugin TSRMLS_CC); mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_pam_authentication_plugin TSRMLS_CC); +#ifdef MYSQLND_HAVE_SSL + mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_sha256_authentication_plugin TSRMLS_CC); +#endif } /* }}} */ diff --git a/ext/mysqlnd/mysqlnd_bt.c b/ext/mysqlnd/mysqlnd_bt.c index 937518405a..73cf1f5a61 100644 --- a/ext/mysqlnd/mysqlnd_bt.c +++ b/ext/mysqlnd/mysqlnd_bt.c @@ -25,252 +25,6 @@ /* Follows code borrowed from zend_builtin_functions.c because the functions there are static */ -#if MYSQLND_UNICODE -/* {{{ gettraceasstring() macros */ -#define TRACE_APPEND_CHR(chr) \ - *str = (char*)erealloc(*str, *len + 1 + 1); \ - (*str)[(*len)++] = chr - -#define TRACE_APPEND_STRL(val, vallen) \ - { \ - int l = vallen; \ - *str = (char*)erealloc(*str, *len + l + 1); \ - memcpy((*str) + *len, val, l); \ - *len += l; \ - } - -#define TRACE_APPEND_USTRL(val, vallen) \ - { \ - zval tmp, copy; \ - int use_copy; \ - ZVAL_UNICODEL(&tmp, val, vallen, 1); \ - zend_make_printable_zval(&tmp, ©, &use_copy); \ - TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \ - zval_dtor(©); \ - zval_dtor(&tmp); \ - } - -#define TRACE_APPEND_ZVAL(zv) \ - if (Z_TYPE_P((zv)) == IS_UNICODE) { \ - zval copy; \ - int use_copy; \ - zend_make_printable_zval((zv), ©, &use_copy); \ - TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \ - zval_dtor(©); \ - } else { \ - TRACE_APPEND_STRL(Z_STRVAL_P((zv)), Z_STRLEN_P((zv))); \ - } - -#define TRACE_APPEND_STR(val) \ - TRACE_APPEND_STRL(val, sizeof(val)-1) - -#define TRACE_APPEND_KEY(key) \ - if (zend_ascii_hash_find(ht, key, sizeof(key), (void**)&tmp) == SUCCESS) { \ - if (Z_TYPE_PP(tmp) == IS_UNICODE) { \ - zval copy; \ - int use_copy; \ - zend_make_printable_zval(*tmp, ©, &use_copy); \ - TRACE_APPEND_STRL(Z_STRVAL(copy), Z_STRLEN(copy)); \ - zval_dtor(©); \ - } else { \ - TRACE_APPEND_STRL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); \ - } \ - } -/* }}} */ - - -/* {{{ mysqlnd_build_trace_args */ -static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) -{ - char **str; - int *len; - - str = va_arg(args, char**); - len = va_arg(args, int*); - - /* the trivial way would be to do: - * conver_to_string_ex(arg); - * append it and kill the now tmp arg. - * but that could cause some E_NOTICE and also damn long lines. - */ - - switch (Z_TYPE_PP(arg)) { - case IS_NULL: - TRACE_APPEND_STR("NULL, "); - break; - case IS_STRING: { - int l_added; - TRACE_APPEND_CHR('\''); - if (Z_STRLEN_PP(arg) > 15) { - TRACE_APPEND_STRL(Z_STRVAL_PP(arg), 15); - TRACE_APPEND_STR("...', "); - l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */ - } else { - l_added = Z_STRLEN_PP(arg); - TRACE_APPEND_STRL(Z_STRVAL_PP(arg), l_added); - TRACE_APPEND_STR("', "); - l_added += 3 + 1; - } - while (--l_added) { - if ((unsigned char)(*str)[*len - l_added] < 32) { - (*str)[*len - l_added] = '?'; - } - } - break; - } - case IS_UNICODE: { - int l_added; - - /* - * We do not want to apply current error mode here, since - * zend_make_printable_zval() uses output encoding converter. - * Temporarily set output encoding converter to escape offending - * chars with \uXXXX notation. - */ - zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, ZEND_CONV_ERROR_ESCAPE_JAVA); - TRACE_APPEND_CHR('\''); - if (Z_USTRLEN_PP(arg) > 15) { - TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), 15); - TRACE_APPEND_STR("...', "); - l_added = 15 + 6 + 1; /* +1 because of while (--l_added) */ - } else { - l_added = Z_USTRLEN_PP(arg); - TRACE_APPEND_USTRL(Z_USTRVAL_PP(arg), l_added); - TRACE_APPEND_STR("', "); - l_added += 3 + 1; - } - /* - * Reset output encoding converter error mode. - */ - zend_set_converter_error_mode(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_FROM_UNICODE, UG(from_error_mode)); - while (--l_added) { - if ((unsigned char)(*str)[*len - l_added] < 32) { - (*str)[*len - l_added] = '?'; - } - } - break; - } - case IS_BOOL: - if (Z_LVAL_PP(arg)) { - TRACE_APPEND_STR("true, "); - } else { - TRACE_APPEND_STR("false, "); - } - break; - case IS_RESOURCE: - TRACE_APPEND_STR("Resource id #"); - /* break; */ - case IS_LONG: { - long lval = Z_LVAL_PP(arg); - char s_tmp[MAX_LENGTH_OF_LONG + 1]; - int l_tmp = zend_sprintf(s_tmp, "%ld", lval); /* SAFE */ - TRACE_APPEND_STRL(s_tmp, l_tmp); - TRACE_APPEND_STR(", "); - break; - } - case IS_DOUBLE: { - double dval = Z_DVAL_PP(arg); - char *s_tmp; - int l_tmp; - - s_tmp = emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1); - l_tmp = zend_sprintf(s_tmp, "%.*G", (int) EG(precision), dval); /* SAFE */ - TRACE_APPEND_STRL(s_tmp, l_tmp); - /* %G already handles removing trailing zeros from the fractional part, yay */ - efree(s_tmp); - TRACE_APPEND_STR(", "); - break; - } - case IS_ARRAY: - TRACE_APPEND_STR("Array, "); - break; - case IS_OBJECT: { - zval tmp; - zstr class_name; - zend_uint class_name_len; - int dup; - - TRACE_APPEND_STR("Object("); - - dup = zend_get_object_classname(*arg, &class_name, &class_name_len TSRMLS_CC); - - ZVAL_UNICODEL(&tmp, class_name.u, class_name_len, 1); - convert_to_string_with_converter(&tmp, ZEND_U_CONVERTER(UG(output_encoding_conv))); - TRACE_APPEND_STRL(Z_STRVAL(tmp), Z_STRLEN(tmp)); - zval_dtor(&tmp); - - if(!dup) { - efree(class_name.v); - } - - TRACE_APPEND_STR("), "); - break; - } - default: - break; - } - return ZEND_HASH_APPLY_KEEP; -} -/* }}} */ - - -static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ -{ - char *s_tmp, **str; - int *len, *num; - long line; - HashTable *ht = Z_ARRVAL_PP(frame); - zval **file, **tmp; - uint * level; - - level = va_arg(args, uint *); - str = va_arg(args, char**); - len = va_arg(args, int*); - num = va_arg(args, int*); - - if (!*level) { - return ZEND_HASH_APPLY_KEEP; - } - --*level; - - s_tmp = emalloc(1 + MAX_LENGTH_OF_LONG + 1 + 1); - sprintf(s_tmp, "#%d ", (*num)++); - TRACE_APPEND_STRL(s_tmp, strlen(s_tmp)); - efree(s_tmp); - if (zend_ascii_hash_find(ht, "file", sizeof("file"), (void**)&file) == SUCCESS) { - if (zend_ascii_hash_find(ht, "line", sizeof("line"), (void**)&tmp) == SUCCESS) { - line = Z_LVAL_PP(tmp); - } else { - line = 0; - } - TRACE_APPEND_ZVAL(*file); - s_tmp = emalloc(MAX_LENGTH_OF_LONG + 2 + 1); - sprintf(s_tmp, "(%ld): ", line); - TRACE_APPEND_STRL(s_tmp, strlen(s_tmp)); - efree(s_tmp); - } else { - TRACE_APPEND_STR("[internal function]: "); - } - TRACE_APPEND_KEY("class"); - TRACE_APPEND_KEY("type"); - TRACE_APPEND_KEY("function"); - TRACE_APPEND_CHR('('); - if (zend_ascii_hash_find(ht, "args", sizeof("args"), (void**)&tmp) == SUCCESS) { - int last_len = *len; - zend_hash_apply_with_arguments(Z_ARRVAL_PP(tmp) TSRMLS_CC, (apply_func_args_t)mysqlnd_build_trace_args, 2, str, len); - if (last_len != *len) { - *len -= 2; /* remove last ', ' */ - } - } - TRACE_APPEND_STR(")\n"); - return ZEND_HASH_APPLY_KEEP; -} -/* }}} */ - - -#else /* PHP 5*/ - - /* {{{ gettraceasstring() macros */ #define TRACE_APPEND_CHR(chr) \ *str = (char*)erealloc(*str, *len + 1 + 1); \ @@ -295,7 +49,8 @@ static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_l /* }}} */ -static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ +static int +mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { char **str; int *len; @@ -391,7 +146,8 @@ static int mysqlnd_build_trace_args(zval **arg TSRMLS_DC, int num_args, va_list } /* }}} */ -static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ +static int +mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key) /* {{{ */ { char *s_tmp, **str; int *len, *num; @@ -442,10 +198,10 @@ static int mysqlnd_build_trace_string(zval **frame TSRMLS_DC, int num_args, va_l return ZEND_HASH_APPLY_KEEP; } /* }}} */ -#endif -PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC) +PHPAPI char * +mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC) { zval *trace; char *res = estrdup(""), **str = &res, *s_tmp; diff --git a/ext/mysqlnd/mysqlnd_debug.c b/ext/mysqlnd/mysqlnd_debug.c index 044a7d6807..5ed2f83731 100644 --- a/ext/mysqlnd/mysqlnd_debug.c +++ b/ext/mysqlnd/mysqlnd_debug.c @@ -747,21 +747,26 @@ mysqlnd_debug_init(const char * skip_functions[] TSRMLS_DC) PHPAPI void _mysqlnd_debug(const char * mode TSRMLS_DC) { #if PHP_DEBUG - MYSQLND_DEBUG *dbg = MYSQLND_G(dbg); + MYSQLND_DEBUG * dbg = MYSQLND_G(dbg); if (!dbg) { - MYSQLND_G(dbg) = dbg = mysqlnd_debug_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC); - if (!dbg) { - return; + struct st_mysqlnd_plugin_trace_log * trace_log_plugin = mysqlnd_plugin_find("debug_trace"); + if (trace_log_plugin) { + dbg = trace_log_plugin->methods.trace_instance_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC); + if (!dbg) { + return; + } + MYSQLND_G(dbg) = dbg; } } - - dbg->m->close(dbg); - dbg->m->set_mode(dbg, mode); - while (zend_stack_count(&dbg->call_stack)) { - zend_stack_del_top(&dbg->call_stack); - } - while (zend_stack_count(&dbg->call_time_stack)) { - zend_stack_del_top(&dbg->call_time_stack); + if (dbg) { + dbg->m->close(dbg); + dbg->m->set_mode(dbg, mode); + while (zend_stack_count(&dbg->call_stack)) { + zend_stack_del_top(&dbg->call_stack); + } + while (zend_stack_count(&dbg->call_time_stack)) { + zend_stack_del_top(&dbg->call_time_stack); + } } #endif } diff --git a/ext/mysqlnd/mysqlnd_debug.h b/ext/mysqlnd/mysqlnd_debug.h index d805178e26..37fbb80360 100644 --- a/ext/mysqlnd/mysqlnd_debug.h +++ b/ext/mysqlnd/mysqlnd_debug.h @@ -96,52 +96,72 @@ PHPAPI char * mysqlnd_get_backtrace(uint max_levels, size_t * length TSRMLS_DC); #define DBG_PROFILE_END_TIME(duration) #endif -#define DBG_INF_EX(dbg_obj, msg) do { if (dbg_skip_trace == FALSE) (dbg_obj)->m->log((dbg_obj), __LINE__, __FILE__, -1, "info : ", (msg)); } while (0) -#define DBG_ERR_EX(dbg_obj, msg) do { if (dbg_skip_trace == FALSE) (dbg_obj)->m->log((dbg_obj), __LINE__, __FILE__, -1, "error: ", (msg)); } while (0) -#define DBG_INF_FMT_EX(dbg_obj, ...) do { if (dbg_skip_trace == FALSE) (dbg_obj)->m->log_va((dbg_obj), __LINE__, __FILE__, -1, "info : ", __VA_ARGS__); } while (0) -#define DBG_ERR_FMT_EX(dbg_obj, ...) do { if (dbg_skip_trace == FALSE) (dbg_obj)->m->log_va((dbg_obj), __LINE__, __FILE__, -1, "error: ", __VA_ARGS__); } while (0) +#define DBG_INF_EX(dbg_obj, msg) do { if (dbg_skip_trace == FALSE && (dbg_obj)) (dbg_obj)->m->log((dbg_obj), __LINE__, __FILE__, -1, "info : ", (msg)); } while (0) +#define DBG_ERR_EX(dbg_obj, msg) do { if (dbg_skip_trace == FALSE && (dbg_obj)) (dbg_obj)->m->log((dbg_obj), __LINE__, __FILE__, -1, "error: ", (msg)); } while (0) +#define DBG_INF_FMT_EX(dbg_obj, ...) do { if (dbg_skip_trace == FALSE && (dbg_obj)) (dbg_obj)->m->log_va((dbg_obj), __LINE__, __FILE__, -1, "info : ", __VA_ARGS__); } while (0) +#define DBG_ERR_FMT_EX(dbg_obj, ...) do { if (dbg_skip_trace == FALSE && (dbg_obj)) (dbg_obj)->m->log_va((dbg_obj), __LINE__, __FILE__, -1, "error: ", __VA_ARGS__); } while (0) -#define DBG_BLOCK_ENTER_EX(dbg_obj, block_name) \ +#define DBG_BLOCK_ENTER_EX(dbg_obj, block_name) DBG_BLOCK_ENTER_EX2((dbg_obj), NULL, (block_name)) +#define DBG_BLOCK_LEAVE_EX(dbg_obj) DBG_BLOCK_LEAVE_EX2((dbg_obj)) + +#define DBG_BLOCK_ENTER_EX2(dbg_obj1, dbg_obj2, block_name) \ { \ - DBG_ENTER_EX(dbg_obj, (block_name)); + DBG_ENTER_EX2((dbg_obj1), (db_obj2), (block_name)); -#define DBG_BLOCK_LEAVE_EX(dbg_obj) \ - DBG_LEAVE_EX((dbg_obj), ;) \ +#define DBG_BLOCK_LEAVE_EX2(dbg_obj1, dbg_obj2) \ + DBG_LEAVE_EX2((dbg_obj1), (dbg_obj2), ;) \ } \ -#define DBG_ENTER_EX(dbg_obj, func_name) \ +#define DBG_ENTER_EX(dbg_obj, func_name) DBG_ENTER_EX2((dbg_obj), (MYSQLND_DEBUG *) NULL, (func_name)) +#define DBG_LEAVE_EX(dbg_obj, leave) DBG_LEAVE_EX2((dbg_obj), (MYSQLND_DEBUG *) NULL, leave) + +#define DBG_ENTER_EX2(dbg_obj1, dbg_obj2, func_name) \ struct timeval __dbg_prof_tp = {0}; \ uint64_t __dbg_prof_start = 0; /* initialization is needed */ \ zend_bool dbg_skip_trace = TRUE; \ - if ((dbg_obj)) { \ - dbg_skip_trace = !(dbg_obj)->m->func_enter((dbg_obj), __LINE__, __FILE__, func_name, strlen(func_name)); \ + if ((dbg_obj1)) { \ + dbg_skip_trace = !(dbg_obj1)->m->func_enter((dbg_obj1), __LINE__, __FILE__, func_name, strlen(func_name)); \ } \ + if ((dbg_obj2)) { \ + dbg_skip_trace |= !(dbg_obj2)->m->func_enter((dbg_obj2), __LINE__, __FILE__, func_name, strlen(func_name)); \ + } \ + if (dbg_skip_trace); /* shut compiler's mouth */\ do { \ - if ((dbg_obj) && (dbg_obj)->flags & MYSQLND_DEBUG_PROFILE_CALLS) { \ + if (((dbg_obj1) && (dbg_obj1)->flags & MYSQLND_DEBUG_PROFILE_CALLS) || \ + ((dbg_obj2) && (dbg_obj2)->flags & MYSQLND_DEBUG_PROFILE_CALLS)) \ + { \ DBG_PROFILE_START_TIME(); \ } \ } while (0); -#define DBG_LEAVE_EX(dbg_obj, leave) \ +#define DBG_LEAVE_EX2(dbg_obj1, dbg_obj2, leave) \ do {\ - if ((dbg_obj)) { \ - uint64_t this_call_duration = 0; \ - if ((dbg_obj)->flags & MYSQLND_DEBUG_PROFILE_CALLS) { \ - DBG_PROFILE_END_TIME(this_call_duration); \ - } \ - (dbg_obj)->m->func_leave((dbg_obj), __LINE__, __FILE__, this_call_duration); \ + uint64_t this_call_duration = 0; \ + if (((dbg_obj1) && (dbg_obj1)->flags & MYSQLND_DEBUG_PROFILE_CALLS) || \ + ((dbg_obj2) && (dbg_obj2)->flags & MYSQLND_DEBUG_PROFILE_CALLS)) \ + { \ + DBG_PROFILE_END_TIME(this_call_duration); \ + } \ + if ((dbg_obj1)) { \ + (dbg_obj1)->m->func_leave((dbg_obj1), __LINE__, __FILE__, this_call_duration); \ + } \ + if ((dbg_obj2)) { \ + (dbg_obj2)->m->func_leave((dbg_obj2), __LINE__, __FILE__, this_call_duration); \ } \ leave \ } while (0); -#define DBG_RETURN_EX(dbg_obj, value) DBG_LEAVE_EX(dbg_obj, return (value);) -#define DBG_VOID_RETURN_EX(dbg_obj) DBG_LEAVE_EX(dbg_obj, return;) +#define DBG_RETURN_EX(dbg_obj, value) DBG_LEAVE_EX((dbg_obj), return (value);) +#define DBG_VOID_RETURN_EX(dbg_obj) DBG_LEAVE_EX((dbg_obj), return;) +#define DBG_RETURN_EX2(dbg_obj1, dbg_obj2, value) DBG_LEAVE_EX2((dbg_obj1), (dbg_obj2), return (value);) +#define DBG_VOID_RETURN_EX2(dbg_obj1, dbg_obj2) DBG_LEAVE_EX2((dbg_obj1), (dbg_obj2), return;) -#else + +#else /* defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 1400)) */ static inline void DBG_INF_EX(MYSQLND_DEBUG * dbg_obj, const char * const msg) {} static inline void DBG_ERR_EX(MYSQLND_DEBUG * dbg_obj, const char * const msg) {} static inline void DBG_INF_FMT_EX(MYSQLND_DEBUG * dbg_obj, ...) {} @@ -167,6 +187,18 @@ static inline void DBG_ENTER_EX(MYSQLND_DEBUG * dbg_obj, const char * const func #define DBG_VOID_RETURN DBG_VOID_RETURN_EX(MYSQLND_G(dbg)) #define DBG_BLOCK_LEAVE DBG_BLOCK_LEAVE_EX(MYSQLND_G(dbg)) + +#define TRACE_ALLOC_INF(msg) DBG_INF_EX(MYSQLND_G(trace_alloc), (msg)) +#define TRACE_ALLOC_ERR(msg) DBG_ERR_EX(MYSQLND_G(trace_alloc), (msg)) +#define TRACE_ALLOC_INF_FMT(...) DBG_INF_FMT_EX(MYSQLND_G(trace_alloc), __VA_ARGS__) +#define TRACE_ALLOC_ERR_FMT(...) DBG_ERR_FMT_EX(MYSQLND_G(trace_alloc), __VA_ARGS__) + +#define TRACE_ALLOC_ENTER(func_name) DBG_ENTER_EX2(MYSQLND_G(dbg), MYSQLND_G(trace_alloc), (func_name)) +#define TRACE_ALLOC_BLOCK_ENTER(bname) DBG_BLOCK_ENTER_EX2(MYSQLND_G(dbg), MYSQLND_G(trace_alloc), (bname)) +#define TRACE_ALLOC_RETURN(value) DBG_RETURN_EX2(MYSQLND_G(dbg), MYSQLND_G(trace_alloc), (value)) +#define TRACE_ALLOC_VOID_RETURN DBG_VOID_RETURN_EX2(MYSQLND_G(dbg), MYSQLND_G(trace_alloc)) +#define TRACE_ALLOC_BLOCK_LEAVE DBG_BLOCK_LEAVE_EX2(MYSQLND_G(dbg), MYSQLND_G(trace_alloc)) + #elif MYSQLND_DBG_ENABLED == 0 static inline void DBG_INF(const char * const msg) {} @@ -175,10 +207,21 @@ static inline void DBG_INF_FMT(const char * const format, ...) {} static inline void DBG_ERR_FMT(const char * const format, ...) {} static inline void DBG_ENTER(const char * const func_name) {} #define DBG_BLOCK_ENTER(bname) { -#define DBG_RETURN(value) return (value) -#define DBG_VOID_RETURN return +#define DBG_RETURN(value) return (value) +#define DBG_VOID_RETURN return #define DBG_BLOCK_LEAVE } + +static inline void TRACE_ALLOC_INF(const char * const msg) {} +static inline void TRACE_ALLOC_ERR(const char * const msg) {} +static inline void TRACE_ALLOC_INF_FMT(const char * const format, ...) {} +static inline void TRACE_ALLOC_ERR_FMT(const char * const format, ...) {} +static inline void TRACE_ALLOC_ENTER(const char * const func_name) {} +#define TRACE_ALLOC_BLOCK_ENTER(bname) { +#define TRACE_ALLOC_RETURN(value) return (value) +#define TRACE_ALLOC_VOID_RETURN return +#define TRACE_ALLOC_BLOCK_LEAVE } + #endif #endif /* MYSQLND_DEBUG_H */ diff --git a/ext/mysqlnd/mysqlnd_driver.c b/ext/mysqlnd/mysqlnd_driver.c index 1ac9bae871..6fab3548f8 100644 --- a/ext/mysqlnd/mysqlnd_driver.c +++ b/ext/mysqlnd/mysqlnd_driver.c @@ -81,7 +81,9 @@ PHPAPI void mysqlnd_library_init(TSRMLS_D) mysqlnd_plugin_core.plugin_header.plugin_stats.values = mysqlnd_global_stats; mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_plugin_core TSRMLS_CC); } +#if defined(MYSQLND_DBG_ENABLED) && MYSQLND_DBG_ENABLED == 1 mysqlnd_example_plugin_register(TSRMLS_C); +#endif mysqlnd_debug_trace_plugin_register(TSRMLS_C); mysqlnd_register_builtin_authentication_plugins(TSRMLS_C); @@ -91,6 +93,7 @@ PHPAPI void mysqlnd_library_init(TSRMLS_D) /* }}} */ + /* {{{ mysqlnd_error_list_pdtor */ static void mysqlnd_error_list_pdtor(void * pDest) @@ -250,17 +253,29 @@ MYSQLND_METHOD(mysqlnd_object_factory, get_prepared_statement)(MYSQLND_CONN_DATA PHPAPI MYSQLND_NET * MYSQLND_METHOD(mysqlnd_object_factory, get_io_channel)(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { - size_t alloc_size = sizeof(MYSQLND_NET) + mysqlnd_plugin_count() * sizeof(void *); - MYSQLND_NET * net = mnd_pecalloc(1, alloc_size, persistent); + size_t net_alloc_size = sizeof(MYSQLND_NET) + mysqlnd_plugin_count() * sizeof(void *); + size_t net_data_alloc_size = sizeof(MYSQLND_NET_DATA) + mysqlnd_plugin_count() * sizeof(void *); + MYSQLND_NET * net = mnd_pecalloc(1, net_alloc_size, persistent); + MYSQLND_NET_DATA * net_data = mnd_pecalloc(1, net_data_alloc_size, persistent); DBG_ENTER("mysqlnd_object_factory::get_io_channel"); DBG_INF_FMT("persistent=%u", persistent); - if (net) { - net->persistent = persistent; - net->m = *mysqlnd_net_get_methods(); + if (net && net_data) { + net->data = net_data; + net->persistent = net->data->persistent = persistent; + net->data->m = *mysqlnd_net_get_methods(); - if (PASS != net->m.init(net, stats, error_info TSRMLS_CC)) { - net->m.dtor(net, stats, error_info TSRMLS_CC); + if (PASS != net->data->m.init(net, stats, error_info TSRMLS_CC)) { + net->data->m.dtor(net, stats, error_info TSRMLS_CC); + net = NULL; + } + } else { + if (net_data) { + mnd_pefree(net_data, persistent); + net_data = NULL; + } + if (net) { + mnd_pefree(net, persistent); net = NULL; } } @@ -270,7 +285,7 @@ MYSQLND_METHOD(mysqlnd_object_factory, get_io_channel)(zend_bool persistent, MYS /* {{{ mysqlnd_object_factory::get_protocol_decoder */ -PHPAPI MYSQLND_PROTOCOL * +static MYSQLND_PROTOCOL * MYSQLND_METHOD(mysqlnd_object_factory, get_protocol_decoder)(zend_bool persistent TSRMLS_DC) { size_t alloc_size = sizeof(MYSQLND_PROTOCOL) + mysqlnd_plugin_count() * sizeof(void *); @@ -288,7 +303,7 @@ MYSQLND_METHOD(mysqlnd_object_factory, get_protocol_decoder)(zend_bool persisten /* }}} */ -MYSQLND_CLASS_METHODS_START(mysqlnd_object_factory) +PHPAPI MYSQLND_CLASS_METHODS_START(mysqlnd_object_factory) MYSQLND_METHOD(mysqlnd_object_factory, get_connection), MYSQLND_METHOD(mysqlnd_object_factory, clone_connection_object), MYSQLND_METHOD(mysqlnd_object_factory, get_prepared_statement), diff --git a/ext/mysqlnd/mysqlnd_enum_n_def.h b/ext/mysqlnd/mysqlnd_enum_n_def.h index b0fe88648e..26ad8815c1 100644 --- a/ext/mysqlnd/mysqlnd_enum_n_def.h +++ b/ext/mysqlnd/mysqlnd_enum_n_def.h @@ -37,6 +37,8 @@ #define MYSQLND_ASSEMBLED_PACKET_MAX_SIZE 3UL*1024UL*1024UL*1024UL +#define MYSQLND_DEFAULT_AUTH_PROTOCOL "mysql_native_password" + #define MYSQLND_ERRMSG_SIZE 512 #define MYSQLND_SQLSTATE_LENGTH 5 #define MYSQLND_SQLSTATE_NULL "00000" @@ -164,9 +166,8 @@ typedef enum mysqlnd_option MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH, -#if MYSQLND_UNICODE - MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE = 200, -#endif + MYSQL_SERVER_PUBLIC_KEY, + MYSQLND_DEPRECATED_ENUM1 = 200, #ifdef MYSQLND_STRING_TO_INT_CONVERSION MYSQLND_OPT_INT_AND_FLOAT_NATIVE = 201, #endif @@ -535,6 +536,8 @@ enum mysqlnd_packet_type PROT_STATS_PACKET, PROT_PREPARE_RESP_PACKET, PROT_CHG_USER_RESP_PACKET, + PROT_SHA256_PK_REQUEST_PACKET, + PROT_SHA256_PK_REQUEST_RESPONSE_PACKET, PROT_LAST /* should always be last */ }; diff --git a/ext/mysqlnd/mysqlnd_ext_plugin.c b/ext/mysqlnd/mysqlnd_ext_plugin.c index 02cd9a891f..2eacac5286 100644 --- a/ext/mysqlnd/mysqlnd_ext_plugin.c +++ b/ext/mysqlnd/mysqlnd_ext_plugin.c @@ -215,7 +215,6 @@ mysqlnd_net_set_methods(struct st_mysqlnd_net_methods * methods) /* }}} */ - /* * Local variables: * tab-width: 4 diff --git a/ext/mysqlnd/mysqlnd_loaddata.c b/ext/mysqlnd/mysqlnd_loaddata.c index 82ee63458e..4655481af9 100644 --- a/ext/mysqlnd/mysqlnd_loaddata.c +++ b/ext/mysqlnd/mysqlnd_loaddata.c @@ -172,7 +172,7 @@ mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zen if (!(conn->options->flags & CLIENT_LOCAL_FILES)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "LOAD DATA LOCAL INFILE forbidden"); /* write empty packet to server */ - ret = net->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC); + ret = net->data->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC); *is_warning = TRUE; goto infile_error; } @@ -192,13 +192,13 @@ mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zen tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf) TSRMLS_CC); SET_CLIENT_ERROR(*conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf); /* write empty packet to server */ - ret = net->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC); + ret = net->data->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC); goto infile_error; } /* read data */ while ((bufsize = infile.local_infile_read (info, buf + MYSQLND_HEADER_SIZE, buflen - MYSQLND_HEADER_SIZE TSRMLS_CC)) > 0) { - if ((ret = net->m.send_ex(net, buf, bufsize, conn->stats, conn->error_info TSRMLS_CC)) == 0) { + if ((ret = net->data->m.send_ex(net, buf, bufsize, conn->stats, conn->error_info TSRMLS_CC)) == 0) { DBG_ERR_FMT("Error during read : %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn); SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn); goto infile_error; @@ -206,7 +206,7 @@ mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zen } /* send empty packet for eof */ - if ((ret = net->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC)) == 0) { + if ((ret = net->data->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info TSRMLS_CC)) == 0) { SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn); goto infile_error; } diff --git a/ext/mysqlnd/mysqlnd_net.c b/ext/mysqlnd/mysqlnd_net.c index 800f577332..5e9f404233 100644 --- a/ext/mysqlnd/mysqlnd_net.c +++ b/ext/mysqlnd/mysqlnd_net.c @@ -67,16 +67,17 @@ MYSQLND_METHOD(mysqlnd_net, network_read_ex)(MYSQLND_NET * const net, zend_uchar MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC) { enum_func_status return_value = PASS; + php_stream * net_stream = net->data->m.get_stream(net TSRMLS_CC); + size_t old_chunk_size = net_stream->chunk_size; size_t to_read = count, ret; - size_t old_chunk_size = net->stream->chunk_size; zend_uchar * p = buffer; DBG_ENTER("mysqlnd_net::network_read_ex"); DBG_INF_FMT("count="MYSQLND_SZ_T_SPEC, count); - net->stream->chunk_size = MIN(to_read, net->options.net_read_buffer_size); + net_stream->chunk_size = MIN(to_read, net->data->options.net_read_buffer_size); while (to_read) { - if (!(ret = php_stream_read(net->stream, (char *) p, to_read))) { + if (!(ret = php_stream_read(net_stream, (char *) p, to_read))) { DBG_ERR_FMT("Error while reading header from socket"); return_value = FAIL; break; @@ -85,7 +86,7 @@ MYSQLND_METHOD(mysqlnd_net, network_read_ex)(MYSQLND_NET * const net, zend_uchar to_read -= ret; } MYSQLND_INC_CONN_STATISTIC_W_VALUE(stats, STAT_BYTES_RECEIVED, count - to_read); - net->stream->chunk_size = old_chunk_size; + net_stream->chunk_size = old_chunk_size; DBG_RETURN(return_value); } /* }}} */ @@ -98,13 +99,13 @@ MYSQLND_METHOD(mysqlnd_net, network_write_ex)(MYSQLND_NET * const net, const zen { size_t ret; DBG_ENTER("mysqlnd_net::network_write_ex"); - ret = php_stream_write(net->stream, (char *)buffer, count); + ret = php_stream_write(net->data->m.get_stream(net TSRMLS_CC), (char *)buffer, count); DBG_RETURN(ret); } /* }}} */ /* {{{ mysqlnd_net::open_pipe */ -static enum_func_status +static php_stream * MYSQLND_METHOD(mysqlnd_net, open_pipe)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC) @@ -114,32 +115,35 @@ MYSQLND_METHOD(mysqlnd_net, open_pipe)(MYSQLND_NET * const net, const char * con #else unsigned int streams_options = 0; #endif + php_stream * net_stream = NULL; + DBG_ENTER("mysqlnd_net::open_pipe"); if (persistent) { streams_options |= STREAM_OPEN_PERSISTENT; } streams_options |= IGNORE_URL; - net->stream = php_stream_open_wrapper((char*) scheme + sizeof("pipe://") - 1, "r+", streams_options, NULL); - if (!net->stream) { + net_stream = php_stream_open_wrapper((char*) scheme + sizeof("pipe://") - 1, "r+", streams_options, NULL); + if (!net_stream) { SET_CLIENT_ERROR(*error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, "Unknown errror while connecting"); - DBG_RETURN(FAIL); + DBG_RETURN(NULL); } /* Streams are not meant for C extensions! Thus we need a hack. Every connected stream will be registered as resource (in EG(regular_list). So far, so good. However, it won't be unregistered yntil the script ends. So, we need to take care of that. */ - net->stream->in_free = 1; - zend_hash_index_del(&EG(regular_list), net->stream->rsrc_id); - net->stream->in_free = 0; + net_stream->in_free = 1; + zend_hash_index_del(&EG(regular_list), net_stream->rsrc_id); + net_stream->in_free = 0; - DBG_RETURN(PASS); + + DBG_RETURN(net_stream); } /* }}} */ /* {{{ mysqlnd_net::open_tcp_or_unix */ -static enum_func_status +static php_stream * MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC) @@ -155,24 +159,27 @@ MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const cha char * errstr = NULL; int errcode = 0; struct timeval tv; + php_stream * net_stream = NULL; DBG_ENTER("mysqlnd_net::open_tcp_or_unix"); + net->data->stream = NULL; + if (persistent) { hashed_details_len = mnd_sprintf(&hashed_details, 0, "%p", net); DBG_INF_FMT("hashed_details=%s", hashed_details); } - if (net->options.timeout_connect) { - tv.tv_sec = net->options.timeout_connect; + if (net->data->options.timeout_connect) { + tv.tv_sec = net->data->options.timeout_connect; tv.tv_usec = 0; } DBG_INF_FMT("calling php_stream_xport_create"); - net->stream = php_stream_xport_create(scheme, scheme_len, streams_options, streams_flags, - hashed_details, (net->options.timeout_connect) ? &tv : NULL, + net_stream = php_stream_xport_create(scheme, scheme_len, streams_options, streams_flags, + hashed_details, (net->data->options.timeout_connect) ? &tv : NULL, NULL /*ctx*/, &errstr, &errcode); - if (errstr || !net->stream) { + if (errstr || !net_stream) { DBG_ERR("Error"); if (hashed_details) { mnd_sprintf_free(hashed_details); @@ -183,7 +190,7 @@ MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const cha /* no mnd_ since we don't allocate it */ efree(errstr); } - DBG_RETURN(FAIL); + DBG_RETURN(NULL); } if (hashed_details) { /* @@ -199,13 +206,13 @@ MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const cha but STREAMS suck big time regarding persistent streams. Just not compatible for extensions that need persistency. */ - net->stream->in_free = 1; + net_stream->in_free = 1; zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_len + 1); - net->stream->in_free = 0; + net_stream->in_free = 0; } #if ZEND_DEBUG /* Shut-up the streams, they don't know what they are doing */ - net->stream->__exposed = 1; + net_stream->__exposed = 1; #endif mnd_sprintf_free(hashed_details); } @@ -215,33 +222,36 @@ MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const cha be registered as resource (in EG(regular_list). So far, so good. However, it won't be unregistered yntil the script ends. So, we need to take care of that. */ - net->stream->in_free = 1; - zend_hash_index_del(&EG(regular_list), net->stream->rsrc_id); - net->stream->in_free = 0; + net_stream->in_free = 1; + zend_hash_index_del(&EG(regular_list), net_stream->rsrc_id); + net_stream->in_free = 0; - DBG_RETURN(PASS); + DBG_RETURN(net_stream); } /* }}} */ -/* {{{ mysqlnd_net::connect_ex */ +/* {{{ mysqlnd_net::post_connect_set_opt */ static void MYSQLND_METHOD(mysqlnd_net, post_connect_set_opt)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC) { + php_stream * net_stream = net->data->m.get_stream(net TSRMLS_CC); DBG_ENTER("mysqlnd_net::post_connect_set_opt"); - if (net->options.timeout_read) { - struct timeval tv; - DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->options.timeout_read); - tv.tv_sec = net->options.timeout_read; - tv.tv_usec = 0; - php_stream_set_option(net->stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv); - } + if (net_stream) { + if (net->data->options.timeout_read) { + struct timeval tv; + DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->data->options.timeout_read); + tv.tv_sec = net->data->options.timeout_read; + tv.tv_usec = 0; + php_stream_set_option(net_stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv); + } - if (!memcmp(scheme, "tcp://", sizeof("tcp://") - 1)) { - /* TCP -> Set TCP_NODELAY */ - mysqlnd_set_sock_no_delay(net->stream TSRMLS_CC); + if (!memcmp(scheme, "tcp://", sizeof("tcp://") - 1)) { + /* TCP -> Set TCP_NODELAY */ + mysqlnd_set_sock_no_delay(net_stream TSRMLS_CC); + } } DBG_VOID_RETURN; @@ -249,6 +259,31 @@ MYSQLND_METHOD(mysqlnd_net, post_connect_set_opt)(MYSQLND_NET * const net, /* }}} */ +/* {{{ mysqlnd_net::get_open_stream */ +static func_mysqlnd_net__open_stream +MYSQLND_METHOD(mysqlnd_net, get_open_stream)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, + MYSQLND_ERROR_INFO * const error_info TSRMLS_DC) +{ + func_mysqlnd_net__open_stream ret = NULL; + DBG_ENTER("mysqlnd_net::get_open_stream"); + if (scheme_len > (sizeof("pipe://") - 1) && !memcmp(scheme, "pipe://", sizeof("pipe://") - 1)) { + ret = net->data->m.open_pipe; + } else if ((scheme_len > (sizeof("tcp://") - 1) && !memcmp(scheme, "tcp://", sizeof("tcp://") - 1)) + || + (scheme_len > (sizeof("unix://") - 1) && !memcmp(scheme, "unix://", sizeof("unix://") - 1))) + { + ret = net->data->m.open_tcp_or_unix; + } + + if (!ret) { + SET_CLIENT_ERROR(*error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, "No handler for this scheme"); + } + + DBG_RETURN(ret); +} +/* }}} */ + + /* {{{ mysqlnd_net::connect_ex */ static enum_func_status MYSQLND_METHOD(mysqlnd_net, connect_ex)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, @@ -261,13 +296,16 @@ MYSQLND_METHOD(mysqlnd_net, connect_ex)(MYSQLND_NET * const net, const char * co net->packet_no = net->compressed_envelope_packet_no = 0; - net->m.close_stream(net, conn_stats, error_info TSRMLS_CC); + net->data->m.close_stream(net, conn_stats, error_info TSRMLS_CC); - open_stream = (scheme_len > (sizeof("pipe://") - 1) && !memcmp(scheme, "pipe://", sizeof("pipe://") - 1))? net->m.open_pipe: - net->m.open_tcp_or_unix; - - if (PASS == (ret = open_stream(net, scheme, scheme_len, persistent, conn_stats, error_info TSRMLS_CC))) { - net->m.post_connect_set_opt(net, scheme, scheme_len, conn_stats, error_info TSRMLS_CC); + open_stream = net->data->m.get_open_stream(net, scheme, scheme_len, error_info TSRMLS_CC); + if (open_stream) { + php_stream * net_stream = open_stream(net, scheme, scheme_len, persistent, conn_stats, error_info TSRMLS_CC); + if (net_stream) { + (void) net->data->m.set_stream(net, net_stream TSRMLS_CC); + net->data->m.post_connect_set_opt(net, scheme, scheme_len, conn_stats, error_info TSRMLS_CC); + ret = PASS; + } } DBG_RETURN(ret); @@ -309,9 +347,9 @@ MYSQLND_METHOD(mysqlnd_net, send_ex)(MYSQLND_NET * const net, zend_uchar * const size_t to_be_sent; DBG_ENTER("mysqlnd_net::send_ex"); - DBG_INF_FMT("count=" MYSQLND_SZ_T_SPEC " compression=%u", count, net->compressed); + DBG_INF_FMT("count=" MYSQLND_SZ_T_SPEC " compression=%u", count, net->data->compressed); - if (net->compressed == TRUE) { + if (net->data->compressed == TRUE) { size_t comp_buf_size = MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE + MIN(left, MYSQLND_MAX_PACKET_SIZE); DBG_INF_FMT("compress_buf_size="MYSQLND_SZ_T_SPEC, comp_buf_size); compress_buf = mnd_emalloc(comp_buf_size); @@ -320,7 +358,7 @@ MYSQLND_METHOD(mysqlnd_net, send_ex)(MYSQLND_NET * const net, zend_uchar * const do { to_be_sent = MIN(left, MYSQLND_MAX_PACKET_SIZE); #ifdef MYSQLND_COMPRESSION_ENABLED - if (net->compressed == TRUE) { + if (net->data->compressed == TRUE) { /* here we need to compress the data and then write it, first comes the compressed header */ size_t tmp_complen = to_be_sent; size_t payload_size; @@ -329,7 +367,7 @@ MYSQLND_METHOD(mysqlnd_net, send_ex)(MYSQLND_NET * const net, zend_uchar * const STORE_HEADER_SIZE(safe_storage, uncompressed_payload); int3store(uncompressed_payload, to_be_sent); int1store(uncompressed_payload + 3, net->packet_no); - if (PASS == net->m.encode((compress_buf + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE), &tmp_complen, + if (PASS == net->data->m.encode((compress_buf + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE), &tmp_complen, uncompressed_payload, to_be_sent + MYSQLND_HEADER_SIZE TSRMLS_CC)) { int3store(compress_buf + MYSQLND_HEADER_SIZE, to_be_sent + MYSQLND_HEADER_SIZE); @@ -344,14 +382,14 @@ MYSQLND_METHOD(mysqlnd_net, send_ex)(MYSQLND_NET * const net, zend_uchar * const int3store(compress_buf, payload_size); int1store(compress_buf + 3, net->packet_no); DBG_INF_FMT("writing "MYSQLND_SZ_T_SPEC" bytes to the network", payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE); - bytes_sent = net->m.network_write_ex(net, compress_buf, payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE, + bytes_sent = net->data->m.network_write_ex(net, compress_buf, payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE, conn_stats, error_info TSRMLS_CC); net->compressed_envelope_packet_no++; #if WHEN_WE_NEED_TO_CHECK_WHETHER_COMPRESSION_WORKS_CORRECTLY if (res == Z_OK) { size_t decompressed_size = left + MYSQLND_HEADER_SIZE; zend_uchar * decompressed_data = mnd_malloc(decompressed_size); - int error = net->m.decode(decompressed_data, decompressed_size, + int error = net->data->m.decode(decompressed_data, decompressed_size, compress_buf + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE, payload_size); if (error == Z_OK) { int i; @@ -376,7 +414,7 @@ MYSQLND_METHOD(mysqlnd_net, send_ex)(MYSQLND_NET * const net, zend_uchar * const STORE_HEADER_SIZE(safe_storage, p); int3store(p, to_be_sent); int1store(p + 3, net->packet_no); - bytes_sent = net->m.network_write_ex(net, p, to_be_sent + MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC); + bytes_sent = net->data->m.network_write_ex(net, p, to_be_sent + MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC); RESTORE_HEADER_SIZE(p, safe_storage); net->compressed_envelope_packet_no++; } @@ -486,13 +524,13 @@ MYSQLND_METHOD(mysqlnd_net, read_compressed_packet_from_stream_and_fill_read_buf (MYSQLND_NET * net, size_t net_payload_size, MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC) { size_t decompressed_size; - enum_func_status ret = PASS; + enum_func_status retval = PASS; zend_uchar * compressed_data = NULL; zend_uchar comp_header[COMPRESSED_HEADER_SIZE]; - DBG_ENTER("mysqlnd_net::read_compressed_packet_from_stream_and_fill_read_buffe"); + DBG_ENTER("mysqlnd_net::read_compressed_packet_from_stream_and_fill_read_buffer"); /* Read the compressed header */ - if (FAIL == net->m.network_read_ex(net, comp_header, COMPRESSED_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) { + if (FAIL == net->data->m.network_read_ex(net, comp_header, COMPRESSED_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) { DBG_RETURN(FAIL); } decompressed_size = uint3korr(comp_header); @@ -502,20 +540,20 @@ MYSQLND_METHOD(mysqlnd_net, read_compressed_packet_from_stream_and_fill_read_buf if (decompressed_size) { compressed_data = mnd_emalloc(net_payload_size); - if (FAIL == net->m.network_read_ex(net, compressed_data, net_payload_size, conn_stats, error_info TSRMLS_CC)) { - ret = FAIL; + if (FAIL == net->data->m.network_read_ex(net, compressed_data, net_payload_size, conn_stats, error_info TSRMLS_CC)) { + retval = FAIL; goto end; } net->uncompressed_data = mysqlnd_create_read_buffer(decompressed_size TSRMLS_CC); - ret = net->m.decode(net->uncompressed_data->data, decompressed_size, compressed_data, net_payload_size TSRMLS_CC); - if (ret == FAIL) { + retval = net->data->m.decode(net->uncompressed_data->data, decompressed_size, compressed_data, net_payload_size TSRMLS_CC); + if (FAIL == retval) { goto end; } } else { DBG_INF_FMT("The server decided not to compress the data. Our job is easy. Copying %u bytes", net_payload_size); net->uncompressed_data = mysqlnd_create_read_buffer(net_payload_size TSRMLS_CC); - if (FAIL == net->m.network_read_ex(net, net->uncompressed_data->data, net_payload_size, conn_stats, error_info TSRMLS_CC)) { - ret = FAIL; + if (FAIL == net->data->m.network_read_ex(net, net->uncompressed_data->data, net_payload_size, conn_stats, error_info TSRMLS_CC)) { + retval = FAIL; goto end; } } @@ -523,7 +561,7 @@ end: if (compressed_data) { mnd_efree(compressed_data); } - DBG_RETURN(ret); + DBG_RETURN(retval); } /* }}} */ #endif /* MYSQLND_COMPRESSION_ENABLED */ @@ -590,16 +628,16 @@ MYSQLND_METHOD(mysqlnd_net, receive_ex)(MYSQLND_NET * const net, zend_uchar * co DBG_ENTER("mysqlnd_net::receive_ex"); #ifdef MYSQLND_COMPRESSION_ENABLED - if (net->compressed) { + if (net->data->compressed) { if (net->uncompressed_data) { size_t to_read_from_buffer = MIN(net->uncompressed_data->bytes_left(net->uncompressed_data), to_read); - DBG_INF_FMT("reading %u from uncompressed_data buffer", to_read_from_buffer); + DBG_INF_FMT("reading "MYSQLND_SZ_T_SPEC" from uncompressed_data buffer", to_read_from_buffer); if (to_read_from_buffer) { net->uncompressed_data->read(net->uncompressed_data, to_read_from_buffer, (zend_uchar *) p); p += to_read_from_buffer; to_read -= to_read_from_buffer; } - DBG_INF_FMT("left %u to read", to_read); + DBG_INF_FMT("left "MYSQLND_SZ_T_SPEC" to read", to_read); if (TRUE == net->uncompressed_data->is_empty(net->uncompressed_data)) { /* Everything was consumed. This should never happen here, but for security */ net->uncompressed_data->free_buffer(&net->uncompressed_data TSRMLS_CC); @@ -610,7 +648,7 @@ MYSQLND_METHOD(mysqlnd_net, receive_ex)(MYSQLND_NET * const net, zend_uchar * co size_t net_payload_size; zend_uchar packet_no; - if (FAIL == net->m.network_read_ex(net, net_header, MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) { + if (FAIL == net->data->m.network_read_ex(net, net_header, MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) { DBG_RETURN(FAIL); } net_payload_size = uint3korr(net_header); @@ -628,7 +666,7 @@ MYSQLND_METHOD(mysqlnd_net, receive_ex)(MYSQLND_NET * const net, zend_uchar * co DBG_INF_FMT("HEADER: hwd_packet_no=%u size=%3u", packet_no, (unsigned long) net_payload_size); #endif /* Now let's read from the wire, decompress it and fill the read buffer */ - net->m.read_compressed_packet_from_stream_and_fill_read_buffer(net, net_payload_size, conn_stats, error_info TSRMLS_CC); + net->data->m.read_compressed_packet_from_stream_and_fill_read_buffer(net, net_payload_size, conn_stats, error_info TSRMLS_CC); /* Now a bit of recursion - read from the read buffer, @@ -636,12 +674,12 @@ MYSQLND_METHOD(mysqlnd_net, receive_ex)(MYSQLND_NET * const net, zend_uchar * co is not enough, then the recursive call will try to satisfy it until it is satisfied. */ - DBG_RETURN(net->m.receive_ex(net, p, to_read, conn_stats, error_info TSRMLS_CC)); + DBG_RETURN(net->data->m.receive_ex(net, p, to_read, conn_stats, error_info TSRMLS_CC)); } DBG_RETURN(PASS); } #endif /* MYSQLND_COMPRESSION_ENABLED */ - DBG_RETURN(net->m.network_read_ex(net, p, to_read, conn_stats, error_info TSRMLS_CC)); + DBG_RETURN(net->data->m.network_read_ex(net, p, to_read, conn_stats, error_info TSRMLS_CC)); } /* }}} */ @@ -659,7 +697,7 @@ MYSQLND_METHOD(mysqlnd_net, set_client_option)(MYSQLND_NET * const net, enum mys DBG_RETURN(FAIL); } net->cmd_buffer.length = *(unsigned int*) value; - DBG_INF_FMT("new_length=%u", net->cmd_buffer.length); + DBG_INF_FMT("new_length="MYSQLND_SZ_T_SPEC, net->cmd_buffer.length); if (!net->cmd_buffer.buffer) { net->cmd_buffer.buffer = mnd_pemalloc(net->cmd_buffer.length, net->persistent); } else { @@ -668,81 +706,90 @@ MYSQLND_METHOD(mysqlnd_net, set_client_option)(MYSQLND_NET * const net, enum mys break; case MYSQLND_OPT_NET_READ_BUFFER_SIZE: DBG_INF("MYSQLND_OPT_NET_READ_BUFFER_SIZE"); - net->options.net_read_buffer_size = *(unsigned int*) value; - DBG_INF_FMT("new_length=%u", net->options.net_read_buffer_size); + net->data->options.net_read_buffer_size = *(unsigned int*) value; + DBG_INF_FMT("new_length="MYSQLND_SZ_T_SPEC, net->data->options.net_read_buffer_size); break; case MYSQL_OPT_CONNECT_TIMEOUT: DBG_INF("MYSQL_OPT_CONNECT_TIMEOUT"); - net->options.timeout_connect = *(unsigned int*) value; + net->data->options.timeout_connect = *(unsigned int*) value; break; case MYSQLND_OPT_SSL_KEY: { zend_bool pers = net->persistent; - if (net->options.ssl_key) { - mnd_pefree(net->options.ssl_key, pers); + if (net->data->options.ssl_key) { + mnd_pefree(net->data->options.ssl_key, pers); } - net->options.ssl_key = value? mnd_pestrdup(value, pers) : NULL; + net->data->options.ssl_key = value? mnd_pestrdup(value, pers) : NULL; break; } case MYSQLND_OPT_SSL_CERT: { zend_bool pers = net->persistent; - if (net->options.ssl_cert) { - mnd_pefree(net->options.ssl_cert, pers); + if (net->data->options.ssl_cert) { + mnd_pefree(net->data->options.ssl_cert, pers); } - net->options.ssl_cert = value? mnd_pestrdup(value, pers) : NULL; + net->data->options.ssl_cert = value? mnd_pestrdup(value, pers) : NULL; break; } case MYSQLND_OPT_SSL_CA: { zend_bool pers = net->persistent; - if (net->options.ssl_ca) { - mnd_pefree(net->options.ssl_ca, pers); + if (net->data->options.ssl_ca) { + mnd_pefree(net->data->options.ssl_ca, pers); } - net->options.ssl_ca = value? mnd_pestrdup(value, pers) : NULL; + net->data->options.ssl_ca = value? mnd_pestrdup(value, pers) : NULL; break; } case MYSQLND_OPT_SSL_CAPATH: { zend_bool pers = net->persistent; - if (net->options.ssl_capath) { - mnd_pefree(net->options.ssl_capath, pers); + if (net->data->options.ssl_capath) { + mnd_pefree(net->data->options.ssl_capath, pers); } - net->options.ssl_capath = value? mnd_pestrdup(value, pers) : NULL; + net->data->options.ssl_capath = value? mnd_pestrdup(value, pers) : NULL; break; } case MYSQLND_OPT_SSL_CIPHER: { zend_bool pers = net->persistent; - if (net->options.ssl_cipher) { - mnd_pefree(net->options.ssl_cipher, pers); + if (net->data->options.ssl_cipher) { + mnd_pefree(net->data->options.ssl_cipher, pers); } - net->options.ssl_cipher = value? mnd_pestrdup(value, pers) : NULL; + net->data->options.ssl_cipher = value? mnd_pestrdup(value, pers) : NULL; break; } case MYSQLND_OPT_SSL_PASSPHRASE: { zend_bool pers = net->persistent; - if (net->options.ssl_passphrase) { - mnd_pefree(net->options.ssl_passphrase, pers); + if (net->data->options.ssl_passphrase) { + mnd_pefree(net->data->options.ssl_passphrase, pers); } - net->options.ssl_passphrase = value? mnd_pestrdup(value, pers) : NULL; + net->data->options.ssl_passphrase = value? mnd_pestrdup(value, pers) : NULL; break; } case MYSQL_OPT_SSL_VERIFY_SERVER_CERT: - net->options.ssl_verify_peer = value? ((*(zend_bool *)value)? TRUE:FALSE): FALSE; + net->data->options.ssl_verify_peer = value? ((*(zend_bool *)value)? TRUE:FALSE): FALSE; break; case MYSQL_OPT_READ_TIMEOUT: - net->options.timeout_read = *(unsigned int*) value; + net->data->options.timeout_read = *(unsigned int*) value; break; #ifdef WHEN_SUPPORTED_BY_MYSQLI case MYSQL_OPT_WRITE_TIMEOUT: - net->options.timeout_write = *(unsigned int*) value; + net->data->options.timeout_write = *(unsigned int*) value; break; #endif case MYSQL_OPT_COMPRESS: - net->options.flags |= MYSQLND_NET_FLAG_USE_COMPRESSION; + net->data->options.flags |= MYSQLND_NET_FLAG_USE_COMPRESSION; break; + case MYSQL_SERVER_PUBLIC_KEY: + { + zend_bool pers = net->persistent; + if (net->data->options.sha256_server_public_key) { + mnd_pefree(net->data->options.sha256_server_public_key, pers); + } + net->data->options.sha256_server_public_key = value? mnd_pestrdup(value, pers) : NULL; + break; + } default: DBG_RETURN(FAIL); } @@ -765,7 +812,8 @@ MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data)(MYSQLND_NET * const net, enum char tmp_buf[256]; size_t skipped_bytes = 0; int opt = PHP_STREAM_OPTION_BLOCKING; - int was_blocked = net->stream->ops->set_option(net->stream, opt, 0, NULL TSRMLS_CC); + php_stream * net_stream = net->data->get_stream(net TSRMLS_CC); + int was_blocked = net_stream->ops->set_option(net_stream, opt, 0, NULL TSRMLS_CC); DBG_ENTER("mysqlnd_net::consume_uneaten_data"); @@ -774,11 +822,11 @@ MYSQLND_METHOD(mysqlnd_net, consume_uneaten_data)(MYSQLND_NET * const net, enum int bytes_consumed; do { - skipped_bytes += (bytes_consumed = php_stream_read(net->stream, tmp_buf, sizeof(tmp_buf))); + skipped_bytes += (bytes_consumed = php_stream_read(net_stream, tmp_buf, sizeof(tmp_buf))); } while (bytes_consumed == sizeof(tmp_buf)); if (was_blocked) { - net->stream->ops->set_option(net->stream, opt, 1, NULL TSRMLS_CC); + net_stream->ops->set_option(net_stream, opt, 1, NULL TSRMLS_CC); } if (bytes_consumed) { @@ -806,58 +854,61 @@ static enum_func_status MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC) { #ifdef MYSQLND_SSL_SUPPORTED - php_stream_context *context = php_stream_context_alloc(TSRMLS_C); + php_stream_context * context = php_stream_context_alloc(TSRMLS_C); + php_stream * net_stream = net->data->m.get_stream(net TSRMLS_CC); + DBG_ENTER("mysqlnd_net::enable_ssl"); if (!context) { DBG_RETURN(FAIL); } - if (net->options.ssl_key) { + if (net->data->options.ssl_key) { zval key_zval; - ZVAL_STRING(&key_zval, net->options.ssl_key, 0); + ZVAL_STRING(&key_zval, net->data->options.ssl_key, 0); php_stream_context_set_option(context, "ssl", "local_pk", &key_zval); } - if (net->options.ssl_verify_peer) { + if (net->data->options.ssl_verify_peer) { zval verify_peer_zval; ZVAL_TRUE(&verify_peer_zval); php_stream_context_set_option(context, "ssl", "verify_peer", &verify_peer_zval); } - if (net->options.ssl_cert) { + if (net->data->options.ssl_cert) { zval cert_zval; - ZVAL_STRING(&cert_zval, net->options.ssl_cert, 0); + ZVAL_STRING(&cert_zval, net->data->options.ssl_cert, 0); php_stream_context_set_option(context, "ssl", "local_cert", &cert_zval); - if (!net->options.ssl_key) { + if (!net->data->options.ssl_key) { php_stream_context_set_option(context, "ssl", "local_pk", &cert_zval); } } - if (net->options.ssl_ca) { + if (net->data->options.ssl_ca) { zval cafile_zval; - ZVAL_STRING(&cafile_zval, net->options.ssl_ca, 0); + ZVAL_STRING(&cafile_zval, net->data->options.ssl_ca, 0); php_stream_context_set_option(context, "ssl", "cafile", &cafile_zval); } - if (net->options.ssl_capath) { + if (net->data->options.ssl_capath) { zval capath_zval; - ZVAL_STRING(&capath_zval, net->options.ssl_capath, 0); + ZVAL_STRING(&capath_zval, net->data->options.ssl_capath, 0); php_stream_context_set_option(context, "ssl", "cafile", &capath_zval); } - if (net->options.ssl_passphrase) { + if (net->data->options.ssl_passphrase) { zval passphrase_zval; - ZVAL_STRING(&passphrase_zval, net->options.ssl_passphrase, 0); + ZVAL_STRING(&passphrase_zval, net->data->options.ssl_passphrase, 0); php_stream_context_set_option(context, "ssl", "passphrase", &passphrase_zval); } - if (net->options.ssl_cipher) { + if (net->data->options.ssl_cipher) { zval cipher_zval; - ZVAL_STRING(&cipher_zval, net->options.ssl_cipher, 0); + ZVAL_STRING(&cipher_zval, net->data->options.ssl_cipher, 0); php_stream_context_set_option(context, "ssl", "ciphers", &cipher_zval); } - php_stream_context_set(net->stream, context); - if (php_stream_xport_crypto_setup(net->stream, STREAM_CRYPTO_METHOD_TLS_CLIENT, NULL TSRMLS_CC) < 0 || - php_stream_xport_crypto_enable(net->stream, 1 TSRMLS_CC) < 0) + php_stream_context_set(net_stream, context); + if (php_stream_xport_crypto_setup(net_stream, STREAM_CRYPTO_METHOD_TLS_CLIENT, NULL TSRMLS_CC) < 0 || + php_stream_xport_crypto_enable(net_stream, 1 TSRMLS_CC) < 0) { DBG_ERR("Cannot connect to MySQL by using SSL"); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot connect to MySQL by using SSL"); DBG_RETURN(FAIL); } + net->data->ssl = TRUE; /* get rid of the context. we are persistent and if this is a real pconn used by mysql/mysqli, then the context would not survive cleaning of EG(regular_list), where it is registered, as a @@ -865,19 +916,20 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net TSRMLS_DC) of the context, which means usage of already freed memory, bad. Actually we don't need this context anymore after we have enabled SSL on the connection. Thus it is very simple, we remove it. */ - php_stream_context_set(net->stream, NULL); + php_stream_context_set(net_stream, NULL); - if (net->options.timeout_read) { + if (net->data->options.timeout_read) { struct timeval tv; - DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->options.timeout_read); - tv.tv_sec = net->options.timeout_read; + DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->data->options.timeout_read); + tv.tv_sec = net->data->options.timeout_read; tv.tv_usec = 0; - php_stream_set_option(net->stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv); + php_stream_set_option(net_stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv); } DBG_RETURN(PASS); #else DBG_ENTER("mysqlnd_net::enable_ssl"); + DBG_INFO("MYSQLND_SSL_SUPPORTED is not defined"); DBG_RETURN(PASS); #endif } @@ -906,25 +958,29 @@ MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET * net TSRMLS_DC) net->uncompressed_data->free_buffer(&net->uncompressed_data TSRMLS_CC); } #endif - if (net->options.ssl_key) { - mnd_pefree(net->options.ssl_key, pers); - net->options.ssl_key = NULL; + if (net->data->options.ssl_key) { + mnd_pefree(net->data->options.ssl_key, pers); + net->data->options.ssl_key = NULL; + } + if (net->data->options.ssl_cert) { + mnd_pefree(net->data->options.ssl_cert, pers); + net->data->options.ssl_cert = NULL; } - if (net->options.ssl_cert) { - mnd_pefree(net->options.ssl_cert, pers); - net->options.ssl_cert = NULL; + if (net->data->options.ssl_ca) { + mnd_pefree(net->data->options.ssl_ca, pers); + net->data->options.ssl_ca = NULL; } - if (net->options.ssl_ca) { - mnd_pefree(net->options.ssl_ca, pers); - net->options.ssl_ca = NULL; + if (net->data->options.ssl_capath) { + mnd_pefree(net->data->options.ssl_capath, pers); + net->data->options.ssl_capath = NULL; } - if (net->options.ssl_capath) { - mnd_pefree(net->options.ssl_capath, pers); - net->options.ssl_capath = NULL; + if (net->data->options.ssl_cipher) { + mnd_pefree(net->data->options.ssl_cipher, pers); + net->data->options.ssl_cipher = NULL; } - if (net->options.ssl_cipher) { - mnd_pefree(net->options.ssl_cipher, pers); - net->options.ssl_cipher = NULL; + if (net->data->options.sha256_server_public_key) { + mnd_pefree(net->data->options.sha256_server_public_key, pers); + net->data->options.sha256_server_public_key = NULL; } DBG_VOID_RETURN; @@ -936,24 +992,25 @@ MYSQLND_METHOD(mysqlnd_net, free_contents)(MYSQLND_NET * net TSRMLS_DC) static void MYSQLND_METHOD(mysqlnd_net, close_stream)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC) { + php_stream * net_stream; DBG_ENTER("mysqlnd_net::close_stream"); - if (net && net->stream) { + if (net && (net_stream = net->data->m.get_stream(net TSRMLS_CC))) { zend_bool pers = net->persistent; - DBG_INF_FMT("Freeing stream. abstract=%p", net->stream->abstract); + DBG_INF_FMT("Freeing stream. abstract=%p", net_stream->abstract); if (pers) { if (EG(active)) { - php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR); + php_stream_free(net_stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR); } else { /* otherwise we will crash because the EG(persistent_list) has been freed already, before the modules are shut down */ - php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR); + php_stream_free(net_stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR); } } else { - php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE); + php_stream_free(net_stream, PHP_STREAM_FREE_CLOSE); } - net->stream = NULL; + (void) net->data->m.set_stream(net, NULL TSRMLS_CC); } DBG_VOID_RETURN; @@ -969,13 +1026,13 @@ MYSQLND_METHOD(mysqlnd_net, init)(MYSQLND_NET * const net, MYSQLND_STATS * const DBG_ENTER("mysqlnd_net::init"); buf_size = MYSQLND_G(net_cmd_buffer_size); /* this is long, cast to unsigned int*/ - net->m.set_client_option(net, MYSQLND_OPT_NET_CMD_BUFFER_SIZE, (char *) &buf_size TSRMLS_CC); + net->data->m.set_client_option(net, MYSQLND_OPT_NET_CMD_BUFFER_SIZE, (char *) &buf_size TSRMLS_CC); buf_size = MYSQLND_G(net_read_buffer_size); /* this is long, cast to unsigned int*/ - net->m.set_client_option(net, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size TSRMLS_CC); + net->data->m.set_client_option(net, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size TSRMLS_CC); buf_size = MYSQLND_G(net_read_timeout); /* this is long, cast to unsigned int*/ - net->m.set_client_option(net, MYSQL_OPT_READ_TIMEOUT, (char *)&buf_size TSRMLS_CC); + net->data->m.set_client_option(net, MYSQL_OPT_READ_TIMEOUT, (char *)&buf_size TSRMLS_CC); DBG_RETURN(PASS); } @@ -988,22 +1045,49 @@ MYSQLND_METHOD(mysqlnd_net, dtor)(MYSQLND_NET * const net, MYSQLND_STATS * const { DBG_ENTER("mysqlnd_net::dtor"); if (net) { - zend_bool pers = net->persistent; - - net->m.free_contents(net TSRMLS_CC); - net->m.close_stream(net, stats, error_info TSRMLS_CC); + net->data->m.free_contents(net TSRMLS_CC); + net->data->m.close_stream(net, stats, error_info TSRMLS_CC); + if (net->cmd_buffer.buffer) { DBG_INF("Freeing cmd buffer"); - mnd_pefree(net->cmd_buffer.buffer, pers); + mnd_pefree(net->cmd_buffer.buffer, net->persistent); net->cmd_buffer.buffer = NULL; } - mnd_pefree(net, pers); + + mnd_pefree(net->data, net->data->persistent); + mnd_pefree(net, net->persistent); } DBG_VOID_RETURN; } /* }}} */ +/* {{{ mysqlnd_net::get_stream */ +static php_stream * +MYSQLND_METHOD(mysqlnd_net, get_stream)(const MYSQLND_NET * const net TSRMLS_DC) +{ + DBG_ENTER("mysqlnd_net::get_stream"); + DBG_INF_FMT("%p", net? net->data->stream:NULL); + DBG_RETURN(net? net->data->stream:NULL); +} +/* }}} */ + + +/* {{{ mysqlnd_net::set_stream */ +static php_stream * +MYSQLND_METHOD(mysqlnd_net, set_stream)(MYSQLND_NET * const net, php_stream * net_stream TSRMLS_DC) +{ + php_stream * ret = NULL; + DBG_ENTER("mysqlnd_net::set_stream"); + if (net) { + net->data->stream = net_stream; + ret = net->data->stream; + } + DBG_RETURN(ret); +} +/* }}} */ + + MYSQLND_CLASS_METHODS_START(mysqlnd_net) MYSQLND_METHOD(mysqlnd_net, init), MYSQLND_METHOD(mysqlnd_net, dtor), @@ -1011,8 +1095,9 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_net) MYSQLND_METHOD(mysqlnd_net, close_stream), MYSQLND_METHOD(mysqlnd_net, open_pipe), MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix), - NULL, /* unused 1 */ - NULL, /* unused 2 */ + MYSQLND_METHOD(mysqlnd_net, get_stream), + MYSQLND_METHOD(mysqlnd_net, set_stream), + MYSQLND_METHOD(mysqlnd_net, get_open_stream), MYSQLND_METHOD(mysqlnd_net, post_connect_set_opt), MYSQLND_METHOD(mysqlnd_net, set_client_option), MYSQLND_METHOD(mysqlnd_net, decode), @@ -1026,10 +1111,15 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_net) MYSQLND_METHOD(mysqlnd_net, send_ex), MYSQLND_METHOD(mysqlnd_net, receive_ex), #ifdef MYSQLND_COMPRESSION_ENABLED - MYSQLND_METHOD(mysqlnd_net, read_compressed_packet_from_stream_and_fill_read_buffer) + MYSQLND_METHOD(mysqlnd_net, read_compressed_packet_from_stream_and_fill_read_buffer), #else - NULL + NULL, #endif + NULL, /* unused 1 */ + NULL, /* unused 2 */ + NULL, /* unused 3 */ + NULL, /* unused 4 */ + NULL /* unused 5 */ MYSQLND_CLASS_METHODS_END; @@ -1051,7 +1141,7 @@ mysqlnd_net_free(MYSQLND_NET * const net, MYSQLND_STATS * stats, MYSQLND_ERROR_I { DBG_ENTER("mysqlnd_net_free"); if (net) { - net->m.dtor(net, stats, error_info TSRMLS_CC); + net->data->m.dtor(net, stats, error_info TSRMLS_CC); } DBG_VOID_RETURN; } diff --git a/ext/mysqlnd/mysqlnd_plugin.c b/ext/mysqlnd/mysqlnd_plugin.c index 2dbb57d1c8..61ab1974f8 100644 --- a/ext/mysqlnd/mysqlnd_plugin.c +++ b/ext/mysqlnd/mysqlnd_plugin.c @@ -26,7 +26,7 @@ #include "mysqlnd_debug.h" /*--------------------------------------------------------------------*/ - +#if defined(MYSQLND_DBG_ENABLED) && MYSQLND_DBG_ENABLED == 1 static enum_func_status mysqlnd_example_plugin_end(void * p TSRMLS_DC); static MYSQLND_STATS * mysqlnd_plugin_example_stats = NULL; @@ -87,7 +87,7 @@ mysqlnd_example_plugin_register(TSRMLS_D) mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_example_plugin TSRMLS_CC); } /* }}} */ - +#endif /* defined(MYSQLND_DBG_ENABLED) && MYSQLND_DBG_ENABLED == 1 */ /*--------------------------------------------------------------------*/ static HashTable mysqlnd_registered_plugins; diff --git a/ext/mysqlnd/mysqlnd_priv.h b/ext/mysqlnd/mysqlnd_priv.h index addce670d4..8fe74cb758 100644 --- a/ext/mysqlnd/mysqlnd_priv.h +++ b/ext/mysqlnd/mysqlnd_priv.h @@ -33,12 +33,6 @@ #define Z_DELREF_PP(ppz) Z_DELREF_P(*(ppz)) #endif -#if PHP_MAJOR_VERSION >= 6 -#define MYSQLND_UNICODE 1 -#else -#define MYSQLND_UNICODE 0 -#endif - #ifdef ZTS #include "TSRM.h" #endif @@ -47,21 +41,12 @@ #define pestrndup(s, length, persistent) ((persistent)?zend_strndup((s),(length)):estrndup((s),(length))) #endif -#if MYSQLND_UNICODE -#define mysqlnd_array_init(arg, field_count) \ -{ \ - ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg));\ - zend_u_hash_init(Z_ARRVAL_P(arg), (field_count), NULL, ZVAL_PTR_DTOR, 0, 0);\ - Z_TYPE_P(arg) = IS_ARRAY;\ -} -#else #define mysqlnd_array_init(arg, field_count) \ { \ ALLOC_HASHTABLE_REL(Z_ARRVAL_P(arg));\ zend_hash_init(Z_ARRVAL_P(arg), (field_count), NULL, ZVAL_PTR_DTOR, 0); \ Z_TYPE_P(arg) = IS_ARRAY;\ } -#endif #define MYSQLND_STR_W_LEN(str) str, (sizeof(str) - 1) @@ -174,9 +159,7 @@ #define CONN_SET_STATE(c, s) (c)->m->set_state((c), (s) TSRMLS_CC) /* PS stuff */ -typedef void (*ps_field_fetch_func)(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, - zend_bool everything_as_unicode TSRMLS_DC); +typedef void (*ps_field_fetch_func)(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC); struct st_mysqlnd_perm_bind { ps_field_fetch_func func; /* should be signed int */ @@ -193,23 +176,21 @@ PHPAPI extern const char * const mysqlnd_out_of_sync; PHPAPI extern const char * const mysqlnd_server_gone; PHPAPI extern const char * const mysqlnd_out_of_memory; -extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_object_factory); -extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_conn); -extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_conn_data); -extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_res); -extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_protocol); -extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_net); +PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_object_factory); +PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_conn); +PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_conn_data); +PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_res); +PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_protocol); +PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_net); -enum_func_status mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char *filename, zend_bool *is_warning TSRMLS_DC); +enum_func_status mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zend_bool * is_warning TSRMLS_DC); void _mysqlnd_init_ps_subsystem();/* This one is private, mysqlnd_library_init() will call it */ void _mysqlnd_init_ps_fetch_subsystem(); -void ps_fetch_from_1_to_8_bytes(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, zend_bool as_unicode, - unsigned int byte_count TSRMLS_DC); +void ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row, unsigned int byte_count TSRMLS_DC); void mysqlnd_plugin_subsystem_init(TSRMLS_D); void mysqlnd_plugin_subsystem_end(TSRMLS_D); diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index 1b48ba1d7b..d5e7d3ffba 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -734,7 +734,6 @@ mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES *result, void *param, unsigned int f current_row, meta->field_count, meta->fields, - result->conn->options->numeric_and_datetime_as_unicode, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC); if (PASS != rc) { @@ -853,7 +852,6 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int result->unbuf->last_row_data, row_packet->field_count, row_packet->fields_metadata, - result->conn->options->numeric_and_datetime_as_unicode, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC)) { @@ -871,14 +869,7 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int zval_dtor(stmt->result_bind[i].zv); #endif if (IS_NULL != (Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(data)) ) { - if ( - (Z_TYPE_P(data) == IS_STRING -#if MYSQLND_UNICODE - || Z_TYPE_P(data) == IS_UNICODE -#endif - ) - && (result->meta->fields[i].max_length < (unsigned long) Z_STRLEN_P(data))) - { + if ((Z_TYPE_P(data) == IS_STRING) && (result->meta->fields[i].max_length < (unsigned long) Z_STRLEN_P(data))) { result->meta->fields[i].max_length = Z_STRLEN_P(data); } stmt->result_bind[i].zv->value = data->value; @@ -1037,7 +1028,6 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla result->unbuf->last_row_data, row_packet->field_count, row_packet->fields_metadata, - result->conn->options->numeric_and_datetime_as_unicode, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC)) { @@ -1058,13 +1048,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla DBG_INF_FMT("i=%u bound_var=%p type=%u refc=%u", i, stmt->result_bind[i].zv, Z_TYPE_P(data), Z_REFCOUNT_P(stmt->result_bind[i].zv)); if (IS_NULL != (Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(data))) { - if ((Z_TYPE_P(data) == IS_STRING -#if MYSQLND_UNICODE - || Z_TYPE_P(data) == IS_UNICODE -#endif - ) - && (result->meta->fields[i].max_length < (unsigned long) Z_STRLEN_P(data))) - { + if ((Z_TYPE_P(data) == IS_STRING) && (result->meta->fields[i].max_length < (unsigned long) Z_STRLEN_P(data))) { result->meta->fields[i].max_length = Z_STRLEN_P(data); } stmt->result_bind[i].zv->value = data->value; diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c index ce0736fdff..95945cf670 100644 --- a/ext/mysqlnd/mysqlnd_ps_codec.c +++ b/ext/mysqlnd/mysqlnd_ps_codec.c @@ -53,9 +53,9 @@ struct st_mysqlnd_perm_bind mysqlnd_ps_fetch_functions[MYSQL_TYPE_LAST + 1]; #define MYSQLND_PS_SKIP_RESULT_STR -2 /* {{{ ps_fetch_from_1_to_8_bytes */ -void ps_fetch_from_1_to_8_bytes(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, zend_bool as_unicode, - unsigned int byte_count TSRMLS_DC) +void +ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, + zend_uchar ** row, unsigned int byte_count TSRMLS_DC) { char tmp[22]; size_t tmp_len = 0; @@ -117,16 +117,7 @@ void ps_fetch_from_1_to_8_bytes(zval *zv, const MYSQLND_FIELD * const field, } if (tmp_len) { -#if MYSQLND_UNICODE - if (as_unicode) { - DBG_INF("stringify"); - ZVAL_UTF8_STRINGL(zv, tmp, tmp_len, ZSTR_DUPLICATE); - } else -#endif - { - DBG_INF("stringify"); - ZVAL_STRINGL(zv, tmp, tmp_len, 1); - } + ZVAL_STRINGL(zv, tmp, tmp_len, 1); } (*row)+= byte_count; DBG_VOID_RETURN; @@ -135,10 +126,8 @@ void ps_fetch_from_1_to_8_bytes(zval *zv, const MYSQLND_FIELD * const field, /* {{{ ps_fetch_null */ -static -void ps_fetch_null(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, - zend_bool as_unicode TSRMLS_DC) +static void +ps_fetch_null(zval *zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { ZVAL_NULL(zv); } @@ -146,54 +135,44 @@ void ps_fetch_null(zval *zv, const MYSQLND_FIELD * const field, /* {{{ ps_fetch_int8 */ -static -void ps_fetch_int8(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, - zend_bool as_unicode TSRMLS_DC) +static void +ps_fetch_int8(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { - ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 1 TSRMLS_CC); + ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 1 TSRMLS_CC); } /* }}} */ /* {{{ ps_fetch_int16 */ -static -void ps_fetch_int16(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, - zend_bool as_unicode TSRMLS_DC) +static void +ps_fetch_int16(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { - ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 2 TSRMLS_CC); + ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 2 TSRMLS_CC); } /* }}} */ /* {{{ ps_fetch_int32 */ -static -void ps_fetch_int32(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, - zend_bool as_unicode TSRMLS_DC) +static void +ps_fetch_int32(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { - ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 4 TSRMLS_CC); + ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 4 TSRMLS_CC); } /* }}} */ /* {{{ ps_fetch_int64 */ -static -void ps_fetch_int64(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, - zend_bool as_unicode TSRMLS_DC) +static void +ps_fetch_int64(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { - ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 8 TSRMLS_CC); + ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 8 TSRMLS_CC); } /* }}} */ /* {{{ ps_fetch_float */ -static -void ps_fetch_float(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, - zend_bool as_unicode TSRMLS_DC) +static void +ps_fetch_float(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { float value; DBG_ENTER("ps_fetch_float"); @@ -207,10 +186,8 @@ void ps_fetch_float(zval *zv, const MYSQLND_FIELD * const field, /* {{{ ps_fetch_double */ -static -void ps_fetch_double(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, - zend_bool as_unicode TSRMLS_DC) +static void +ps_fetch_double(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { double value; DBG_ENTER("ps_fetch_double"); @@ -224,18 +201,16 @@ void ps_fetch_double(zval *zv, const MYSQLND_FIELD * const field, /* {{{ ps_fetch_time */ -static -void ps_fetch_time(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, - zend_bool as_unicode TSRMLS_DC) +static void +ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { struct st_mysqlnd_time t; - unsigned int length; /* First byte encodes the length*/ + unsigned long length; /* First byte encodes the length*/ char * value; DBG_ENTER("ps_fetch_time"); if ((length = php_mysqlnd_net_field_length(row))) { - zend_uchar *to= *row; + zend_uchar * to= *row; t.time_type = MYSQLND_TIMESTAMP_TIME; t.neg = (zend_bool) to[0]; @@ -261,29 +236,19 @@ void ps_fetch_time(zval *zv, const MYSQLND_FIELD * const field, length = mnd_sprintf(&value, 0, "%s%02u:%02u:%02u", (t.neg ? "-" : ""), t.hour, t.minute, t.second); DBG_INF_FMT("%s", value); -#if MYSQLND_UNICODE - if (!as_unicode) { -#endif - ZVAL_STRINGL(zv, value, length, 1); - mnd_sprintf_free(value); -#if MYSQLND_UNICODE - } else { - ZVAL_UTF8_STRINGL(zv, value, length, ZSTR_AUTOFREE); - } -#endif + ZVAL_STRINGL(zv, value, length, 1); + mnd_sprintf_free(value); DBG_VOID_RETURN; } /* }}} */ /* {{{ ps_fetch_date */ -static -void ps_fetch_date(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, - zend_bool as_unicode TSRMLS_DC) +static void +ps_fetch_date(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { struct st_mysqlnd_time t = {0}; - unsigned int length; /* First byte encodes the length*/ + unsigned long length; /* First byte encodes the length*/ char * value; DBG_ENTER("ps_fetch_date"); @@ -308,34 +273,24 @@ void ps_fetch_date(zval *zv, const MYSQLND_FIELD * const field, length = mnd_sprintf(&value, 0, "%04u-%02u-%02u", t.year, t.month, t.day); DBG_INF_FMT("%s", value); -#if MYSQLND_UNICODE - if (!as_unicode) { -#endif - ZVAL_STRINGL(zv, value, length, 1); - mnd_sprintf_free(value); -#if MYSQLND_UNICODE - } else { - ZVAL_UTF8_STRINGL(zv, value, length, ZSTR_AUTOFREE); - } -#endif + ZVAL_STRINGL(zv, value, length, 1); + mnd_sprintf_free(value); DBG_VOID_RETURN; } /* }}} */ /* {{{ ps_fetch_datetime */ -static -void ps_fetch_datetime(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, - zend_bool as_unicode TSRMLS_DC) +static void +ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { struct st_mysqlnd_time t; - unsigned int length; /* First byte encodes the length*/ + unsigned long length; /* First byte encodes the length*/ char * value; DBG_ENTER("ps_fetch_datetime"); if ((length = php_mysqlnd_net_field_length(row))) { - zend_uchar *to= *row; + zend_uchar * to = *row; t.time_type = MYSQLND_TIMESTAMP_DATETIME; t.neg = 0; @@ -362,46 +317,26 @@ void ps_fetch_datetime(zval *zv, const MYSQLND_FIELD * const field, length = mnd_sprintf(&value, 0, "%04u-%02u-%02u %02u:%02u:%02u", t.year, t.month, t.day, t.hour, t.minute, t.second); DBG_INF_FMT("%s", value); -#if MYSQLND_UNICODE - if (!as_unicode) { -#endif - ZVAL_STRINGL(zv, value, length, 1); - mnd_sprintf_free(value); -#if MYSQLND_UNICODE - } else { - ZVAL_UTF8_STRINGL(zv, to, length, ZSTR_AUTOFREE); - } -#endif + ZVAL_STRINGL(zv, value, length, 1); + mnd_sprintf_free(value); DBG_VOID_RETURN; } /* }}} */ /* {{{ ps_fetch_string */ -static -void ps_fetch_string(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, - zend_bool as_unicode TSRMLS_DC) +static void +ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { /* For now just copy, before we make it possible to write \0 to the row buffer */ - unsigned long length = php_mysqlnd_net_field_length(row); + const unsigned long length = php_mysqlnd_net_field_length(row); DBG_ENTER("ps_fetch_string"); DBG_INF_FMT("len = %lu", length); -#if MYSQLND_UNICODE - if (field->charsetnr == MYSQLND_BINARY_CHARSET_NR) { - DBG_INF("Binary charset"); - ZVAL_STRINGL(zv, (char *)*row, length, 1); - } else { - DBG_INF_FMT("copying from the row buffer"); - ZVAL_UTF8_STRINGL(zv, (char*)*row, length, ZSTR_DUPLICATE); - } -#else DBG_INF("copying from the row buffer"); ZVAL_STRINGL(zv, (char *)*row, length, 1); -#endif (*row) += length; DBG_VOID_RETURN; @@ -410,13 +345,11 @@ void ps_fetch_string(zval *zv, const MYSQLND_FIELD * const field, /* {{{ ps_fetch_bit */ -static -void ps_fetch_bit(zval *zv, const MYSQLND_FIELD * const field, - unsigned int pack_len, zend_uchar **row, - zend_bool as_unicode TSRMLS_DC) +static void +ps_fetch_bit(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row TSRMLS_DC) { - unsigned long length= php_mysqlnd_net_field_length(row); - ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, length TSRMLS_CC); + unsigned long length = php_mysqlnd_net_field_length(row); + ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, length TSRMLS_CC); } /* }}} */ @@ -566,7 +499,7 @@ void _mysqlnd_init_ps_fetch_subsystem() /* {{{ mysqlnd_stmt_copy_it */ static enum_func_status -mysqlnd_stmt_copy_it(zval *** copies, zval *original, unsigned int param_count, unsigned int current TSRMLS_DC) +mysqlnd_stmt_copy_it(zval *** copies, zval * original, unsigned int param_count, unsigned int current TSRMLS_DC) { if (!*copies) { *copies = mnd_ecalloc(param_count, sizeof(zval *)); @@ -786,12 +719,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar case MYSQL_TYPE_VAR_STRING: use_string: data_size += 8; /* max 8 bytes for size */ -#if MYSQLND_UNICODE - if (Z_TYPE_P(the_var) != IS_STRING || Z_TYPE_P(the_var) == IS_UNICODE) -#else - if (Z_TYPE_P(the_var) != IS_STRING) -#endif - { + if (Z_TYPE_P(the_var) != IS_STRING) { if (!copies || !copies[i]) { if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) { SET_OOM_ERROR(*stmt->error_info); @@ -799,11 +727,6 @@ use_string: } } the_var = copies[i]; -#if MYSQLND_UNICODE - if (Z_TYPE_P(the_var) == IS_UNICODE) { - zval_unicode_to_string_ex(the_var, UG(utf8_conv) TSRMLS_CC); - } -#endif } convert_to_string_ex(&the_var); data_size += Z_STRLEN_P(the_var); diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 8ae2665ba7..3dd06edb34 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -55,7 +55,6 @@ MYSQLND_METHOD(mysqlnd_res, initialize_result_set_rest)(MYSQLND_RES * const resu data_cursor, result->meta->field_count, result->meta->fields, - result->conn->options->numeric_and_datetime_as_unicode, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC); if (rc != PASS) { @@ -106,16 +105,6 @@ mysqlnd_rset_zval_ptr_dtor(zval **zv, enum_mysqlnd_res_type type, zend_bool * co /* Not a prepared statement, then we have to call copy_ctor and then zval_ptr_dtor() - - In Unicode mode the destruction of the zvals should not call - zval_copy_ctor() because then we will leak. - I suppose we can use UG(unicode) in mysqlnd.c when freeing a result set - to check if we need to call copy_ctor(). - - If the type is IS_UNICODE, which can happen with PHP6, then we don't - need to copy_ctor, as the data doesn't point to our internal buffers. - If it's string (in PHP5 always) and in PHP6 if data is binary, then - it still points to internal buffers and has to be copied. */ if (Z_TYPE_PP(zv) == IS_STRING) { zval_copy_ctor(*zv); @@ -669,7 +658,6 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES * result TSRMLS_DC) result->unbuf->last_row_data, row_packet->field_count, row_packet->fields_metadata, - result->conn->options->numeric_and_datetime_as_unicode, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC); if (PASS != rc) { @@ -784,7 +772,6 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla result->unbuf->last_row_data, field_count, row_packet->fields_metadata, - result->conn->options->numeric_and_datetime_as_unicode, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC); if (PASS != rc) { @@ -812,19 +799,11 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES * result, void *param, unsigned int fla */ Z_ADDREF_P(data); if (hash_key->is_numeric == FALSE) { -#if MYSQLND_UNICODE - zend_u_hash_quick_update(Z_ARRVAL_P(row), IS_UNICODE, - hash_key->ustr, - hash_key->ulen + 1, - hash_key->key, - (void *) &data, sizeof(zval *), NULL); -#else zend_hash_quick_update(Z_ARRVAL_P(row), field->name, field->name_length + 1, hash_key->key, (void *) &data, sizeof(zval *), NULL); -#endif } else { zend_hash_index_update(Z_ARRVAL_P(row), hash_key->key, @@ -950,7 +929,6 @@ mysqlnd_fetch_row_buffered_c(MYSQLND_RES * result TSRMLS_DC) current_row, result->meta->field_count, result->meta->fields, - result->conn->options->numeric_and_datetime_as_unicode, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC); if (rc != PASS) { @@ -1023,7 +1001,6 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags current_row, result->meta->field_count, result->meta->fields, - result->conn->options->numeric_and_datetime_as_unicode, result->conn->options->int_and_float_native, result->conn->stats TSRMLS_CC); if (rc != PASS) { @@ -1062,19 +1039,11 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES * result, void *param, unsigned int flags */ Z_ADDREF_P(data); if (hash_key->is_numeric == FALSE) { -#if MYSQLND_UNICODE - zend_u_hash_quick_update(Z_ARRVAL_P(row), IS_UNICODE, - hash_key->ustr, - hash_key->ulen + 1, - hash_key->key, - (void *) &data, sizeof(zval *), NULL); -#else zend_hash_quick_update(Z_ARRVAL_P(row), field->name, field->name_length + 1, hash_key->key, (void *) &data, sizeof(zval *), NULL); -#endif } else { zend_hash_index_update(Z_ARRVAL_P(row), hash_key->key, diff --git a/ext/mysqlnd/mysqlnd_result_meta.c b/ext/mysqlnd/mysqlnd_result_meta.c index 9469ceaf11..53368a8fb8 100644 --- a/ext/mysqlnd/mysqlnd_result_meta.c +++ b/ext/mysqlnd/mysqlnd_result_meta.c @@ -92,60 +92,12 @@ mysqlnd_is_key_numeric(const char * key, size_t length, long *idx) /* }}} */ -#if MYSQLND_UNICODE -/* {{{ mysqlnd_unicode_is_key_numeric */ -static zend_bool -mysqlnd_unicode_is_key_numeric(UChar *key, size_t length, long *idx) -{ - register UChar * tmp=key; - - if (*tmp==0x2D /*'-'*/) { - tmp++; - } - if ((*tmp>=0x30 /*'0'*/ && *tmp<=0x39 /*'9'*/)) { /* possibly a numeric index */ - do { - UChar *end=key+length-1; - - if (*tmp++==0x30 && length>2) { /* don't accept numbers with leading zeros */ - break; - } - while (tmp<end) { - if (!(*tmp>=0x30 /*'0'*/ && *tmp<=0x39 /*'9'*/)) { - break; - } - tmp++; - } - if (tmp==end && *tmp==0) { /* a numeric index */ - if (*key==0x2D /*'-'*/) { - *idx = zend_u_strtol(key, NULL, 10); - if (*idx!=LONG_MIN) { - return TRUE; - } - } else { - *idx = zend_u_strtol(key, NULL, 10); - if (*idx!=LONG_MAX) { - return TRUE; - } - } - } - } while (0); - } - return FALSE; -} -/* }}} */ -#endif - - /* {{{ mysqlnd_res_meta::read_metadata */ static enum_func_status MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn TSRMLS_DC) { unsigned int i = 0; MYSQLND_PACKET_RES_FIELD * field_packet; -#if MYSQLND_UNICODE - UChar *ustr; - int ulen; -#endif DBG_ENTER("mysqlnd_res_meta::read_metadata"); @@ -226,21 +178,6 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met } } -#if MYSQLND_UNICODE - zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, - meta->fields[i].name, - meta->fields[i].name_length TSRMLS_CC); - if ((meta->zend_hash_keys[i].is_numeric = - mysqlnd_unicode_is_key_numeric(ustr, ulen + 1, &idx))) - { - meta->zend_hash_keys[i].key = idx; - mnd_efree(ustr); - } else { - meta->zend_hash_keys[i].ustr.u = ustr; - meta->zend_hash_keys[i].ulen = ulen; - meta->zend_hash_keys[i].key = zend_u_get_hash_value(IS_UNICODE, ZSTR(ustr), ulen + 1); - } -#else /* For BC we have to check whether the key is numeric and use it like this */ if ((meta->zend_hash_keys[i].is_numeric = mysqlnd_is_key_numeric(field_packet->metadata->name, @@ -253,7 +190,6 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met zend_get_hash_value(field_packet->metadata->name, field_packet->metadata->name_length + 1); } -#endif } PACKET_FREE(field_packet); @@ -283,15 +219,6 @@ MYSQLND_METHOD(mysqlnd_res_meta, free)(MYSQLND_RES_METADATA * meta TSRMLS_DC) if (meta->zend_hash_keys) { DBG_INF("Freeing zend_hash_keys"); -#if MYSQLND_UNICODE - if (UG(unicode)) { - for (i = 0; i < meta->field_count; i++) { - if (meta->zend_hash_keys[i].ustr.v) { - mnd_pefree(meta->zend_hash_keys[i].ustr.v, meta->persistent); - } - } - } -#endif mnd_pefree(meta->zend_hash_keys, meta->persistent); meta->zend_hash_keys = NULL; } @@ -379,15 +306,6 @@ MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * co /* copy the trailing \0 too */ memcpy(new_fields[i].def, orig_fields[i].def, orig_fields[i].def_length + 1); } -#if MYSQLND_UNICODE - if (new_meta->zend_hash_keys[i].ustr.u) { - new_meta->zend_hash_keys[i].ustr.u = - eustrndup(new_meta->zend_hash_keys[i].ustr.u, new_meta->zend_hash_keys[i].ulen); - if (!new_meta->zend_hash_keys[i].ustr.u) { - goto oom; - } - } -#endif } new_meta->current_field = 0; new_meta->field_count = meta->field_count; diff --git a/ext/mysqlnd/mysqlnd_reverse_api.h b/ext/mysqlnd/mysqlnd_reverse_api.h index 005df5a1ab..7e780edb52 100644 --- a/ext/mysqlnd/mysqlnd_reverse_api.h +++ b/ext/mysqlnd/mysqlnd_reverse_api.h @@ -47,4 +47,3 @@ PHPAPI MYSQLND * zval_to_mysqlnd(zval * zv TSRMLS_DC); * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ - diff --git a/ext/mysqlnd/mysqlnd_statistics.c b/ext/mysqlnd/mysqlnd_statistics.c index bb00a9192d..00145a3dbc 100644 --- a/ext/mysqlnd/mysqlnd_statistics.c +++ b/ext/mysqlnd/mysqlnd_statistics.c @@ -203,22 +203,10 @@ mysqlnd_fill_stats_hash(const MYSQLND_STATS * const stats, const MYSQLND_STRING mysqlnd_array_init(return_value, stats->count); for (i = 0; i < stats->count; i++) { -#if MYSQLND_UNICODE - UChar *ustr, *tstr; - int ulen, tlen; -#endif char tmp[25]; sprintf((char *)&tmp, MYSQLND_LLU_SPEC, stats->values[i]); -#if MYSQLND_UNICODE - zend_string_to_unicode(UG(utf8_conv), &ustr, &ulen, names[i].s, names[i].l + 1 TSRMLS_CC); - zend_string_to_unicode(UG(utf8_conv), &tstr, &tlen, tmp, strlen(tmp) + 1 TSRMLS_CC); - add_u_assoc_unicode_ex(return_value, IS_UNICODE, ZSTR(ustr), ulen, tstr, 1); - efree(ustr); - efree(tstr); -#else add_assoc_string_ex(return_value, names[i].s, names[i].l + 1, tmp, 1); -#endif } } /* }}} */ diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h index 43eba40a20..28def72599 100644 --- a/ext/mysqlnd/mysqlnd_structs.h +++ b/ext/mysqlnd/mysqlnd_structs.h @@ -183,7 +183,6 @@ typedef struct st_mysqlnd_options /* maximum allowed packet size for communication */ ulong max_allowed_packet; - zend_bool numeric_and_datetime_as_unicode; #ifdef MYSQLND_STRING_TO_INT_CONVERSION zend_bool int_and_float_native; #endif @@ -207,12 +206,20 @@ typedef struct st_mysqlnd_net_options char *ssl_passphrase; zend_bool ssl_verify_peer; uint64_t flags; + + char * sha256_server_public_key; + + char * unused1; + char * unused2; + char * unused3; + char * unused4; } MYSQLND_NET_OPTIONS; typedef struct st_mysqlnd_connection MYSQLND; typedef struct st_mysqlnd_connection_data MYSQLND_CONN_DATA; typedef struct st_mysqlnd_net MYSQLND_NET; +typedef struct st_mysqlnd_net_data MYSQLND_NET_DATA; typedef struct st_mysqlnd_protocol MYSQLND_PROTOCOL; typedef struct st_mysqlnd_res MYSQLND_RES; typedef char** MYSQLND_ROW_C; /* return data as array of strings */ @@ -282,7 +289,10 @@ typedef enum_func_status (*func_mysqlnd_net__init)(MYSQLND_NET * const net, MYSQ typedef void (*func_mysqlnd_net__dtor)(MYSQLND_NET * const net, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_net__connect_ex)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC); typedef void (*func_mysqlnd_net__close_stream)(MYSQLND_NET * const net, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC); -typedef enum_func_status (*func_mysqlnd_net__open_stream)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC); +typedef php_stream * (*func_mysqlnd_net__open_stream)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC); +typedef php_stream * (*func_mysqlnd_net__get_stream)(const MYSQLND_NET * const net TSRMLS_DC); +typedef php_stream * (*func_mysqlnd_net__set_stream)(MYSQLND_NET * const net, php_stream * net_stream TSRMLS_DC); +typedef func_mysqlnd_net__open_stream (*func_mysqlnd_net__get_open_stream)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC); typedef void (*func_mysqlnd_net__post_connect_set_opt)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_net__read_compressed_packet_from_stream_and_fill_read_buffer)(MYSQLND_NET * net, size_t net_payload_size, MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info TSRMLS_DC); @@ -295,8 +305,10 @@ struct st_mysqlnd_net_methods func_mysqlnd_net__open_stream open_pipe; func_mysqlnd_net__open_stream open_tcp_or_unix; - void * unused1; - void * unused2; + func_mysqlnd_net__get_stream get_stream; + func_mysqlnd_net__set_stream set_stream; + func_mysqlnd_net__get_open_stream get_open_stream; + func_mysqlnd_net__post_connect_set_opt post_connect_set_opt; func_mysqlnd_net__set_client_option set_client_option; @@ -314,11 +326,11 @@ struct st_mysqlnd_net_methods func_mysqlnd_net__read_compressed_packet_from_stream_and_fill_read_buffer read_compressed_packet_from_stream_and_fill_read_buffer; + void * unused1; + void * unused2; void * unused3; void * unused4; void * unused5; - void * unused6; - void * unused7; }; @@ -335,6 +347,8 @@ struct st_mysqlnd_packet_stats; struct st_mysqlnd_packet_prepare_response; struct st_mysqlnd_packet_chg_user_resp; struct st_mysqlnd_packet_auth_pam; +struct st_mysqlnd_packet_sha256_pk_request; +struct st_mysqlnd_packet_sha256_pk_request_response; typedef struct st_mysqlnd_packet_greet * (*func_mysqlnd_protocol__get_greet_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); typedef struct st_mysqlnd_packet_auth * (*func_mysqlnd_protocol__get_auth_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); @@ -349,6 +363,8 @@ typedef struct st_mysqlnd_packet_row * (*func_mysqlnd_protocol__get_row_packet typedef struct st_mysqlnd_packet_stats * (*func_mysqlnd_protocol__get_stats_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); typedef struct st_mysqlnd_packet_prepare_response *(*func_mysqlnd_protocol__get_prepare_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); typedef struct st_mysqlnd_packet_chg_user_resp*(*func_mysqlnd_protocol__get_change_user_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); +typedef struct st_mysqlnd_packet_sha256_pk_request *(*func_mysqlnd_protocol__get_sha256_pk_request_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); +typedef struct st_mysqlnd_packet_sha256_pk_request_response *(*func_mysqlnd_protocol__get_sha256_pk_request_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC); struct st_mysqlnd_protocol_methods { @@ -365,12 +381,12 @@ struct st_mysqlnd_protocol_methods func_mysqlnd_protocol__get_stats_packet get_stats_packet; func_mysqlnd_protocol__get_prepare_response_packet get_prepare_response_packet; func_mysqlnd_protocol__get_change_user_response_packet get_change_user_response_packet; + func_mysqlnd_protocol__get_sha256_pk_request_packet get_sha256_pk_request_packet; + func_mysqlnd_protocol__get_sha256_pk_request_response_packet get_sha256_pk_request_response_packet; void * unused1; void * unused2; void * unused3; - void * unused4; - void * unused5; }; @@ -447,7 +463,7 @@ typedef enum_func_status (*func_mysqlnd_conn_data__query_read_result_set_header) typedef MYSQLND_CONN_DATA * (*func_mysqlnd_conn_data__get_reference)(MYSQLND_CONN_DATA * const conn TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_conn_data__free_reference)(MYSQLND_CONN_DATA * const conn TSRMLS_DC); -typedef enum mysqlnd_connection_state (*func_mysqlnd_conn_data__get_state)(MYSQLND_CONN_DATA * const conn TSRMLS_DC); +typedef enum mysqlnd_connection_state (*func_mysqlnd_conn_data__get_state)(const MYSQLND_CONN_DATA * const conn TSRMLS_DC); typedef void (*func_mysqlnd_conn_data__set_state)(MYSQLND_CONN_DATA * const conn, enum mysqlnd_connection_state new_state TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_conn_data__simple_command)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, const zend_uchar * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent, zend_bool ignore_upsert_status TSRMLS_DC); @@ -467,7 +483,11 @@ typedef enum_func_status (*func_mysqlnd_conn_data__tx_rollback)(MYSQLND_CONN_DAT typedef enum_func_status (*func_mysqlnd_conn_data__local_tx_start)(MYSQLND_CONN_DATA * conn, size_t this_func TSRMLS_DC); typedef enum_func_status (*func_mysqlnd_conn_data__local_tx_end)(MYSQLND_CONN_DATA * conn, size_t this_func, enum_func_status status TSRMLS_DC); - +typedef enum_func_status (*func_mysqlnd_conn_data__execute_init_commands)(MYSQLND_CONN_DATA * conn TSRMLS_DC); +typedef unsigned int (*func_mysqlnd_conn_data__get_updated_connect_flags)(MYSQLND_CONN_DATA * conn, unsigned int mysql_flags TSRMLS_DC); +typedef enum_func_status (*func_mysqlnd_conn_data__connect_handshake)(MYSQLND_CONN_DATA * conn, const char * const host, const char * const user, const char * const passwd, const unsigned int passwd_len, const char * const db, const unsigned int db_len, const unsigned int mysql_flags TSRMLS_DC); +typedef enum_func_status (*func_mysqlnd_conn_data__simple_command_send_request)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, const zend_uchar * const arg, size_t arg_len, zend_bool silent, zend_bool ignore_upsert_status TSRMLS_DC); +typedef struct st_mysqlnd_authentication_plugin * (*func_mysqlnd_conn_data__fetch_auth_plugin_by_name)(const char * const requested_protocol TSRMLS_DC); struct st_mysqlnd_conn_data_methods { @@ -547,6 +567,12 @@ struct st_mysqlnd_conn_data_methods func_mysqlnd_conn_data__local_tx_start local_tx_start; func_mysqlnd_conn_data__local_tx_end local_tx_end; + + func_mysqlnd_conn_data__execute_init_commands execute_init_commands; + func_mysqlnd_conn_data__get_updated_connect_flags get_updated_connect_flags; + func_mysqlnd_conn_data__connect_handshake connect_handshake; + func_mysqlnd_conn_data__simple_command_send_request simple_command_send_request; + func_mysqlnd_conn_data__fetch_auth_plugin_by_name fetch_auth_plugin_by_name; }; @@ -598,9 +624,8 @@ typedef void (*func_mysqlnd_res__unbuffered_free_last_data)(MYSQLND_RES *resu /* for decoding - binary or text protocol */ typedef enum_func_status (*func_mysqlnd_res__row_decoder)(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields, - unsigned int field_count, MYSQLND_FIELD *fields_metadata, - zend_bool as_unicode, zend_bool as_int_or_float, - MYSQLND_STATS * stats TSRMLS_DC); + unsigned int field_count, const MYSQLND_FIELD * fields_metadata, + zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC); typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res__result_meta_init)(unsigned int field_count, zend_bool persistent TSRMLS_DC); @@ -768,31 +793,44 @@ struct st_mysqlnd_stmt_methods }; -struct st_mysqlnd_net +struct st_mysqlnd_net_data { php_stream *stream; + zend_bool compressed; + zend_bool ssl; +#ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND + zend_uchar last_command; +#else + zend_uchar unused_pad1; +#endif + MYSQLND_NET_OPTIONS options; + + unsigned int refcount; + + zend_bool persistent; + + struct st_mysqlnd_net_methods m; +}; + + +struct st_mysqlnd_net +{ + struct st_mysqlnd_net_data * data; + /* sequence for simple checking of correct packets */ zend_uchar packet_no; - zend_bool compressed; zend_uchar compressed_envelope_packet_no; + #ifdef MYSQLND_COMPRESSION_ENABLED MYSQLND_READ_BUFFER * uncompressed_data; #else void * unused_pad1; #endif -#ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND - zend_uchar last_command; -#else - zend_uchar unused_pad2; -#endif + /* cmd buffer */ MYSQLND_CMD_BUFFER cmd_buffer; - MYSQLND_NET_OPTIONS options; - - zend_bool persistent; - - struct st_mysqlnd_net_methods m; + zend_bool persistent; }; @@ -893,10 +931,6 @@ struct mysqlnd_field_hash_key { zend_bool is_numeric; unsigned long key; -#if MYSQLND_UNICODE - zstr ustr; - unsigned int ulen; -#endif }; @@ -1070,7 +1104,8 @@ typedef zend_uchar * (*func_auth_plugin__get_auth_data)(struct st_mysqlnd_authen size_t * auth_data_len, MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd, const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len, - const MYSQLND_OPTIONS * const options, unsigned long mysql_flags + const MYSQLND_OPTIONS * const options, + const MYSQLND_NET_OPTIONS * const net_options, unsigned long mysql_flags TSRMLS_DC); struct st_mysqlnd_authentication_plugin diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index face502cd6..65db8f0b2a 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -47,7 +47,7 @@ (buf_size), (packet)->header.size, (packet)->header.size - (buf_size)); \ DBG_RETURN(FAIL); \ }\ - if (FAIL == conn->net->m.receive_ex((conn)->net, (buf), (packet)->header.size, (conn)->stats, ((conn)->error_info) TSRMLS_CC)) { \ + if (FAIL == conn->net->data->m.receive_ex((conn)->net, (buf), (packet)->header.size, (conn)->stats, ((conn)->error_info) TSRMLS_CC)) { \ CONN_SET_STATE(conn, CONN_QUIT_SENT); \ SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);\ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", mysqlnd_server_gone); \ @@ -264,8 +264,8 @@ mysqlnd_read_header(MYSQLND_NET * net, MYSQLND_PACKET_HEADER * header, zend_uchar buffer[MYSQLND_HEADER_SIZE]; DBG_ENTER(mysqlnd_read_header_name); - DBG_INF_FMT("compressed=%u", net->compressed); - if (FAIL == net->m.receive_ex(net, buffer, MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) { + DBG_INF_FMT("compressed=%u", net->data->compressed); + if (FAIL == net->data->m.receive_ex(net, buffer, MYSQLND_HEADER_SIZE, conn_stats, error_info TSRMLS_CC)) { DBG_RETURN(FAIL); } @@ -279,7 +279,7 @@ mysqlnd_read_header(MYSQLND_NET * net, MYSQLND_PACKET_HEADER * header, STAT_PROTOCOL_OVERHEAD_IN, MYSQLND_HEADER_SIZE, STAT_PACKETS_RECEIVED, 1); - if (net->compressed || net->packet_no == header->packet_no) { + if (net->data->compressed || net->packet_no == header->packet_no) { /* Have to increase the number, so we can send correct number back. It will round at 255 as this is unsigned char. The server needs this for simple @@ -549,7 +549,7 @@ size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC } DBG_RETURN(p - buffer - MYSQLND_HEADER_SIZE); } else { - size_t sent = conn->net->m.send_ex(conn->net, buffer, p - buffer - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info TSRMLS_CC); + size_t sent = conn->net->data->m.send_ex(conn->net, buffer, p - buffer - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info TSRMLS_CC); if (!sent) { CONN_SET_STATE(conn, CONN_QUIT_SENT); } @@ -623,7 +623,7 @@ php_mysqlnd_auth_response_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_D memcpy(packet->new_auth_protocol_data, p, packet->new_auth_protocol_data_len); } DBG_INF_FMT("The server requested switching auth plugin to : %s", packet->new_auth_protocol); - DBG_INF_FMT("Server salt : [%*s]", packet->new_auth_protocol_data_len, packet->new_auth_protocol_data); + DBG_INF_FMT("Server salt : [%d][%.*s]", packet->new_auth_protocol_data_len, packet->new_auth_protocol_data_len, packet->new_auth_protocol_data); } } else { /* Everything was fine! */ @@ -709,7 +709,7 @@ php_mysqlnd_change_auth_response_write(void * _packet, MYSQLND_CONN_DATA * conn } { - size_t sent = conn->net->m.send_ex(conn->net, buffer, p - buffer - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info TSRMLS_CC); + size_t sent = conn->net->data->m.send_ex(conn->net, buffer, p - buffer - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info TSRMLS_CC); if (buffer != conn->net->cmd_buffer.buffer) { mnd_efree(buffer); } @@ -923,14 +923,14 @@ size_t php_mysqlnd_cmd_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC) MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_PACKETS_SENT_CMD); #ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND - net->m.consume_uneaten_data(net, packet->command TSRMLS_CC); + net->data->m.consume_uneaten_data(net, packet->command TSRMLS_CC); #endif if (!packet->argument || !packet->arg_len) { zend_uchar buffer[MYSQLND_HEADER_SIZE + 1]; int1store(buffer + MYSQLND_HEADER_SIZE, packet->command); - sent = net->m.send_ex(net, buffer, 1, conn->stats, conn->error_info TSRMLS_CC); + sent = net->data->m.send_ex(net, buffer, 1, conn->stats, conn->error_info TSRMLS_CC); } else { size_t tmp_len = packet->arg_len + 1 + MYSQLND_HEADER_SIZE; zend_uchar *tmp, *p; @@ -945,7 +945,7 @@ size_t php_mysqlnd_cmd_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC) memcpy(p, packet->argument, packet->arg_len); - sent = net->m.send_ex(net, tmp, tmp_len - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info TSRMLS_CC); + sent = net->data->m.send_ex(net, tmp, tmp_len - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info TSRMLS_CC); if (tmp != net->cmd_buffer.buffer) { MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CMD_BUFFER_TOO_SMALL); mnd_efree(tmp); @@ -1388,7 +1388,7 @@ php_mysqlnd_read_row_ex(MYSQLND_CONN_DATA * conn, MYSQLND_MEMORY_POOL * result_s p = (*buffer)->ptr + (*data_size - header.size); } - if (PASS != (ret = conn->net->m.receive_ex(conn->net, p, header.size, conn->stats, conn->error_info TSRMLS_CC))) { + if (PASS != (ret = conn->net->data->m.receive_ex(conn->net, p, header.size, conn->stats, conn->error_info TSRMLS_CC))) { DBG_ERR("Empty row packet body"); php_error(E_WARNING, "Empty row packet body"); break; @@ -1411,9 +1411,8 @@ php_mysqlnd_read_row_ex(MYSQLND_CONN_DATA * conn, MYSQLND_MEMORY_POOL * result_s /* {{{ php_mysqlnd_rowp_read_binary_protocol */ enum_func_status php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields, - unsigned int field_count, MYSQLND_FIELD *fields_metadata, - zend_bool as_unicode, zend_bool as_int_or_float, - MYSQLND_STATS * stats TSRMLS_DC) + unsigned int field_count, const MYSQLND_FIELD * fields_metadata, + zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC) { unsigned int i; zend_uchar * p = row_buffer->ptr; @@ -1446,17 +1445,17 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv enum_mysqlnd_collected_stats statistic; zend_uchar * orig_p = p; - DBG_INF_FMT("Into zval=%p decoding column %u [%s.%s.%s] type=%u field->flags&unsigned=%u flags=%u is_bit=%u as_unicode=%u", + DBG_INF_FMT("Into zval=%p decoding column %u [%s.%s.%s] type=%u field->flags&unsigned=%u flags=%u is_bit=%u", *current_field, i, fields_metadata[i].db, fields_metadata[i].table, fields_metadata[i].name, fields_metadata[i].type, - fields_metadata[i].flags & UNSIGNED_FLAG, fields_metadata[i].flags, fields_metadata[i].type == MYSQL_TYPE_BIT, as_unicode); + fields_metadata[i].flags & UNSIGNED_FLAG, fields_metadata[i].flags, fields_metadata[i].type == MYSQL_TYPE_BIT); if (*null_ptr & bit) { DBG_INF("It's null"); ZVAL_NULL(*current_field); statistic = STAT_BINARY_TYPE_FETCHED_NULL; } else { enum_mysqlnd_field_types type = fields_metadata[i].type; - mysqlnd_ps_fetch_functions[type].func(*current_field, &fields_metadata[i], 0, &p, as_unicode TSRMLS_CC); + mysqlnd_ps_fetch_functions[type].func(*current_field, &fields_metadata[i], 0, &p TSRMLS_CC); if (MYSQLND_G(collect_statistics)) { switch (fields_metadata[i].type) { @@ -1510,9 +1509,8 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv /* {{{ php_mysqlnd_rowp_read_text_protocol */ enum_func_status php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields, - unsigned int field_count, MYSQLND_FIELD *fields_metadata, - zend_bool as_unicode, zend_bool as_int_or_float, - MYSQLND_STATS * stats TSRMLS_DC) + unsigned int field_count, const MYSQLND_FIELD * fields_metadata, + zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC) { unsigned int i; zend_bool last_field_was_string = FALSE; @@ -1564,7 +1562,7 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ZVAL_NULL(*current_field); last_field_was_string = FALSE; } else { -#if MYSQLND_UNICODE || defined(MYSQLND_STRING_TO_INT_CONVERSION) +#if defined(MYSQLND_STRING_TO_INT_CONVERSION) struct st_mysqlnd_perm_bind perm_bind = mysqlnd_ps_fetch_functions[fields_metadata[i].type]; #endif @@ -1660,7 +1658,7 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval Definitely not nice, _hackish_ :(, but works. */ zend_uchar *start = bit_area; - ps_fetch_from_1_to_8_bytes(*current_field, &(fields_metadata[i]), 0, &p, as_unicode, len TSRMLS_CC); + ps_fetch_from_1_to_8_bytes(*current_field, &(fields_metadata[i]), 0, &p, len TSRMLS_CC); /* We have advanced in ps_fetch_from_1_to_8_bytes. We should go back because later in this function there will be an advancement. @@ -1668,60 +1666,16 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval p -= len; if (Z_TYPE_PP(current_field) == IS_LONG) { bit_area += 1 + sprintf((char *)start, "%ld", Z_LVAL_PP(current_field)); -#if MYSQLND_UNICODE - if (as_unicode) { - ZVAL_UTF8_STRINGL(*current_field, start, bit_area - start - 1, 0); - } else -#endif - { - ZVAL_STRINGL(*current_field, (char *) start, bit_area - start - 1, 0); - } + ZVAL_STRINGL(*current_field, (char *) start, bit_area - start - 1, 0); } else if (Z_TYPE_PP(current_field) == IS_STRING){ memcpy(bit_area, Z_STRVAL_PP(current_field), Z_STRLEN_PP(current_field)); bit_area += Z_STRLEN_PP(current_field); *bit_area++ = '\0'; zval_dtor(*current_field); -#if MYSQLND_UNICODE - if (as_unicode) { - ZVAL_UTF8_STRINGL(*current_field, start, bit_area - start - 1, 0); - } else -#endif - { - ZVAL_STRINGL(*current_field, (char *) start, bit_area - start - 1, 0); - } + ZVAL_STRINGL(*current_field, (char *) start, bit_area - start - 1, 0); } - /* - IS_UNICODE should not be specially handled. In unicode mode - the buffers are not referenced - everything is copied. - */ } else -#if MYSQLND_UNICODE == 0 - { - ZVAL_STRINGL(*current_field, (char *)p, len, 0); - } -#else - /* - Here we have to convert to UTF16, which means not reusing the buffer. - Which in turn means that we can free the buffers once we have - stored the result set, if we use store_result(). - - Also the destruction of the zvals should not call zval_copy_ctor() - because then we will leak. - - XXX: Keep in mind that up there there is an open `else` in - #ifdef MYSQLND_STRING_TO_INT_CONVERSION - which will make with this `if` an `else if`. - */ - if ((perm_bind.is_possibly_blob == TRUE && - fields_metadata[i].charsetnr == MYSQLND_BINARY_CHARSET_NR) || - (!as_unicode && perm_bind.can_ret_as_str_in_uni == TRUE)) - { - /* BLOB - no conversion please */ - ZVAL_STRINGL(*current_field, (char *)p, len, 0); - } else { - ZVAL_UTF8_STRINGL(*current_field, (char *)p, len, 0); - } -#endif + ZVAL_STRINGL(*current_field, (char *)p, len, 0); p += len; last_field_was_string = TRUE; } @@ -1744,10 +1698,8 @@ php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval static enum_func_status php_mysqlnd_rowp_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC) { - MYSQLND_NET * net = conn->net; zend_uchar *p; enum_func_status ret = PASS; - size_t old_chunk_size = net->stream->chunk_size; MYSQLND_PACKET_ROW *packet= (MYSQLND_PACKET_ROW *) _packet; size_t post_alloc_for_bit_fields = 0; size_t data_size = 0; @@ -1829,7 +1781,6 @@ php_mysqlnd_rowp_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC) } end: - net->stream->chunk_size = old_chunk_size; DBG_RETURN(ret); } /* }}} */ @@ -2081,6 +2032,89 @@ php_mysqlnd_chg_user_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_ /* }}} */ +/* {{{ php_mysqlnd_sha256_pk_request_write */ +static +size_t php_mysqlnd_sha256_pk_request_write(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC) +{ + zend_uchar buffer[MYSQLND_HEADER_SIZE + 1]; + size_t sent; + + DBG_ENTER("php_mysqlnd_sha256_pk_request_write"); + + int1store(buffer + MYSQLND_HEADER_SIZE, '\1'); + sent = conn->net->data->m.send_ex(conn->net, buffer, 1, conn->stats, conn->error_info TSRMLS_CC); + + DBG_RETURN(sent); +} +/* }}} */ + + +/* {{{ php_mysqlnd_sha256_pk_request_free_mem */ +static +void php_mysqlnd_sha256_pk_request_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC) +{ + if (!stack_allocation) { + MYSQLND_PACKET_SHA256_PK_REQUEST * p = (MYSQLND_PACKET_SHA256_PK_REQUEST *) _packet; + mnd_pefree(p, p->header.persistent); + } +} +/* }}} */ + + +#define SHA256_PK_REQUEST_RESP_BUFFER_SIZE 2048 + +/* {{{ php_mysqlnd_sha256_pk_request_response_read */ +static enum_func_status +php_mysqlnd_sha256_pk_request_response_read(void * _packet, MYSQLND_CONN_DATA * conn TSRMLS_DC) +{ + zend_uchar buf[SHA256_PK_REQUEST_RESP_BUFFER_SIZE]; + zend_uchar *p = buf; + zend_uchar *begin = buf; + MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE * packet= (MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE *) _packet; + + DBG_ENTER("php_mysqlnd_sha256_pk_request_response_read"); + + /* leave space for terminating safety \0 */ + PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "SHA256_PK_REQUEST_RESPONSE", PROT_SHA256_PK_REQUEST_RESPONSE_PACKET); + BAIL_IF_NO_MORE_DATA; + + p++; + BAIL_IF_NO_MORE_DATA; + + packet->public_key_len = packet->header.size - (p - buf); + packet->public_key = mnd_emalloc(packet->public_key_len + 1); + memcpy(packet->public_key, p, packet->public_key_len); + packet->public_key[packet->public_key_len] = '\0'; + + DBG_RETURN(PASS); + +premature_end: + DBG_ERR_FMT("OK packet %d bytes shorter than expected", p - begin - packet->header.size); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "SHA256_PK_REQUEST_RESPONSE packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected", + p - begin - packet->header.size); + DBG_RETURN(FAIL); +} +/* }}} */ + + +/* {{{ php_mysqlnd_sha256_pk_request_response_free_mem */ +static void +php_mysqlnd_sha256_pk_request_response_free_mem(void * _packet, zend_bool stack_allocation TSRMLS_DC) +{ + MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE * p = (MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE *) _packet; + if (p->public_key) { + mnd_efree(p->public_key); + p->public_key = NULL; + } + p->public_key_len = 0; + + if (!stack_allocation) { + mnd_pefree(p, p->header.persistent); + } +} +/* }}} */ + + /* {{{ packet_methods */ static mysqlnd_packet_methods packet_methods[PROT_LAST] = @@ -2162,7 +2196,19 @@ mysqlnd_packet_methods packet_methods[PROT_LAST] = php_mysqlnd_chg_user_read, /* read */ NULL, /* write */ php_mysqlnd_chg_user_free_mem, - } /* PROT_CHG_USER_RESP_PACKET */ + }, /* PROT_CHG_USER_RESP_PACKET */ + { + sizeof(MYSQLND_PACKET_SHA256_PK_REQUEST), + NULL, /* read */ + php_mysqlnd_sha256_pk_request_write, + php_mysqlnd_sha256_pk_request_free_mem, + }, /* PROT_SHA256_PK_REQUEST_PACKET */ + { + sizeof(MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE), + php_mysqlnd_sha256_pk_request_response_read, + NULL, /* write */ + php_mysqlnd_sha256_pk_request_response_free_mem, + } /* PROT_SHA256_PK_REQUEST_RESPONSE_PACKET */ }; /* }}} */ @@ -2362,6 +2408,37 @@ MYSQLND_METHOD(mysqlnd_protocol, get_change_user_response_packet)(MYSQLND_PROTOC /* }}} */ +/* {{{ mysqlnd_protocol::get_sha256_pk_request_packet */ +static struct st_mysqlnd_packet_sha256_pk_request * +MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC) +{ + struct st_mysqlnd_packet_sha256_pk_request * packet = mnd_pecalloc(1, packet_methods[PROT_SHA256_PK_REQUEST_PACKET].struct_size, persistent); + DBG_ENTER("mysqlnd_protocol::get_sha256_pk_request_packet"); + if (packet) { + packet->header.m = &packet_methods[PROT_SHA256_PK_REQUEST_PACKET]; + packet->header.persistent = persistent; + } + DBG_RETURN(packet); +} +/* }}} */ + + +/* {{{ mysqlnd_protocol::get_sha256_pk_request_response_packet */ +static struct st_mysqlnd_packet_sha256_pk_request_response * +MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent TSRMLS_DC) +{ + struct st_mysqlnd_packet_sha256_pk_request_response * packet = mnd_pecalloc(1, packet_methods[PROT_SHA256_PK_REQUEST_RESPONSE_PACKET].struct_size, persistent); + DBG_ENTER("mysqlnd_protocol::get_sha256_pk_request_response_packet"); + if (packet) { + packet->header.m = &packet_methods[PROT_SHA256_PK_REQUEST_RESPONSE_PACKET]; + packet->header.persistent = persistent; + } + DBG_RETURN(packet); +} +/* }}} */ + + + MYSQLND_CLASS_METHODS_START(mysqlnd_protocol) MYSQLND_METHOD(mysqlnd_protocol, get_greet_packet), MYSQLND_METHOD(mysqlnd_protocol, get_auth_packet), @@ -2375,7 +2452,9 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_protocol) MYSQLND_METHOD(mysqlnd_protocol, get_row_packet), MYSQLND_METHOD(mysqlnd_protocol, get_stats_packet), MYSQLND_METHOD(mysqlnd_protocol, get_prepare_response_packet), - MYSQLND_METHOD(mysqlnd_protocol, get_change_user_response_packet) + MYSQLND_METHOD(mysqlnd_protocol, get_change_user_response_packet), + MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_packet), + MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_response_packet) MYSQLND_CLASS_METHODS_END; diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.h b/ext/mysqlnd/mysqlnd_wireprotocol.h index 96322d7060..92c8e502de 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.h +++ b/ext/mysqlnd/mysqlnd_wireprotocol.h @@ -286,6 +286,18 @@ typedef struct st_mysqlnd_packet_chg_user_resp { } MYSQLND_PACKET_CHG_USER_RESPONSE; +/* Command packet */ +typedef struct st_mysqlnd_packet_sha256_pk_request { + MYSQLND_PACKET_HEADER header; +} MYSQLND_PACKET_SHA256_PK_REQUEST; + +typedef struct st_mysqlnd_packet_sha256_pk_request_response { + MYSQLND_PACKET_HEADER header; + zend_uchar *public_key; + size_t public_key_len; +} MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE; + + PHPAPI void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const pass, size_t pass_len); unsigned long php_mysqlnd_net_field_length(zend_uchar **packet); @@ -295,15 +307,13 @@ PHPAPI const extern char * const mysqlnd_empty_string; enum_func_status php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields, - unsigned int field_count, MYSQLND_FIELD *fields_metadata, - zend_bool as_unicode, zend_bool as_int_or_float, - MYSQLND_STATS * stats TSRMLS_DC); + unsigned int field_count, const MYSQLND_FIELD * fields_metadata, + zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC); enum_func_status php_mysqlnd_rowp_read_text_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields, - unsigned int field_count, MYSQLND_FIELD *fields_metadata, - zend_bool as_unicode, zend_bool as_int_or_float, - MYSQLND_STATS * stats TSRMLS_DC); + unsigned int field_count, const MYSQLND_FIELD * fields_metadata, + zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC); PHPAPI MYSQLND_PROTOCOL * mysqlnd_protocol_init(zend_bool persistent TSRMLS_DC); diff --git a/ext/mysqlnd/php_mysqlnd.c b/ext/mysqlnd/php_mysqlnd.c index 20fcc5e7ad..9bc6b8fb5b 100644 --- a/ext/mysqlnd/php_mysqlnd.c +++ b/ext/mysqlnd/php_mysqlnd.c @@ -40,39 +40,8 @@ static zend_function_entry mysqlnd_functions[] = { /* {{{ mysqlnd_minfo_print_hash */ -#if MYSQLND_UNICODE -PHPAPI void mysqlnd_minfo_print_hash(zval *values) -{ - zval **values_entry; - HashPosition pos_values; - - zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos_values); - while (zend_hash_get_current_data_ex(Z_ARRVAL_P(values), - (void **)&values_entry, &pos_values) == SUCCESS) { - zstr string_key; - uint string_key_len; - ulong num_key; - int s_len; - char *s = NULL; - - TSRMLS_FETCH(); - zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &string_key, &string_key_len, &num_key, 0, &pos_values); - - convert_to_string(*values_entry); - - if (zend_unicode_to_string(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), - &s, &s_len, string_key.u, string_key_len TSRMLS_CC) == SUCCESS) { - php_info_print_table_row(2, s, Z_STRVAL_PP(values_entry)); - } - if (s) { - mnd_efree(s); - } - - zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos_values); - } -} -#else -PHPAPI void mysqlnd_minfo_print_hash(zval *values) +PHPAPI void +mysqlnd_minfo_print_hash(zval *values) { zval **values_entry; HashPosition pos_values; @@ -91,7 +60,6 @@ PHPAPI void mysqlnd_minfo_print_hash(zval *values) zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos_values); } } -#endif /* }}} */ @@ -170,12 +138,18 @@ PHP_MINFO_FUNCTION(mysqlnd) #else "not supported"); #endif - php_info_print_table_row(2, "SSL", + php_info_print_table_row(2, "core SSL", #ifdef MYSQLND_SSL_SUPPORTED "supported"); #else "not supported"); #endif + php_info_print_table_row(2, "extended SSL", +#ifdef MYSQLND_HAVE_SSL + "supported"); +#else + "not supported"); +#endif snprintf(buf, sizeof(buf), "%ld", MYSQLND_G(net_cmd_buffer_size)); php_info_print_table_row(2, "Command buffer size", buf); snprintf(buf, sizeof(buf), "%ld", MYSQLND_G(net_read_buffer_size)); @@ -221,6 +195,8 @@ static PHP_GINIT_FUNCTION(mysqlnd) mysqlnd_globals->collect_memory_statistics = FALSE; mysqlnd_globals->debug = NULL; /* The actual string */ mysqlnd_globals->dbg = NULL; /* The DBG object*/ + mysqlnd_globals->trace_alloc_settings = NULL; + mysqlnd_globals->trace_alloc = NULL; mysqlnd_globals->net_cmd_buffer_size = MYSQLND_NET_CMD_BUFFER_MIN_SIZE; mysqlnd_globals->net_read_buffer_size = 32768; mysqlnd_globals->net_read_timeout = 31536000; @@ -232,6 +208,7 @@ static PHP_GINIT_FUNCTION(mysqlnd) mysqlnd_globals->debug_malloc_fail_threshold = -1; mysqlnd_globals->debug_calloc_fail_threshold = -1; mysqlnd_globals->debug_realloc_fail_threshold = -1; + mysqlnd_globals->sha256_server_public_key = NULL; } /* }}} */ @@ -253,11 +230,13 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("mysqlnd.collect_statistics", "1", PHP_INI_ALL, OnUpdateBool, collect_statistics, zend_mysqlnd_globals, mysqlnd_globals) STD_PHP_INI_BOOLEAN("mysqlnd.collect_memory_statistics", "0", PHP_INI_SYSTEM, OnUpdateBool, collect_memory_statistics, zend_mysqlnd_globals, mysqlnd_globals) STD_PHP_INI_ENTRY("mysqlnd.debug", NULL, PHP_INI_SYSTEM, OnUpdateString, debug, zend_mysqlnd_globals, mysqlnd_globals) + STD_PHP_INI_ENTRY("mysqlnd.trace_alloc", NULL, PHP_INI_SYSTEM, OnUpdateString, trace_alloc_settings, zend_mysqlnd_globals, mysqlnd_globals) STD_PHP_INI_ENTRY("mysqlnd.net_cmd_buffer_size", MYSQLND_NET_CMD_BUFFER_MIN_SIZE_STR, PHP_INI_ALL, OnUpdateNetCmdBufferSize, net_cmd_buffer_size, zend_mysqlnd_globals, mysqlnd_globals) STD_PHP_INI_ENTRY("mysqlnd.net_read_buffer_size", "32768",PHP_INI_ALL, OnUpdateLong, net_read_buffer_size, zend_mysqlnd_globals, mysqlnd_globals) STD_PHP_INI_ENTRY("mysqlnd.net_read_timeout", "31536000", PHP_INI_SYSTEM, OnUpdateLong, net_read_timeout, zend_mysqlnd_globals, mysqlnd_globals) STD_PHP_INI_ENTRY("mysqlnd.log_mask", "0", PHP_INI_ALL, OnUpdateLong, log_mask, zend_mysqlnd_globals, mysqlnd_globals) STD_PHP_INI_ENTRY("mysqlnd.mempool_default_size","16000", PHP_INI_ALL, OnUpdateLong, mempool_default_size, zend_mysqlnd_globals, mysqlnd_globals) + STD_PHP_INI_ENTRY("mysqlnd.sha256_server_public_key",NULL, PHP_INI_PERDIR, OnUpdateString, sha256_server_public_key, zend_mysqlnd_globals, mysqlnd_globals) #if PHP_DEBUG STD_PHP_INI_ENTRY("mysqlnd.debug_emalloc_fail_threshold","-1", PHP_INI_SYSTEM, OnUpdateLong, debug_emalloc_fail_threshold, zend_mysqlnd_globals, mysqlnd_globals) @@ -306,11 +285,14 @@ static PHP_RINIT_FUNCTION(mysqlnd) MYSQLND_G(dbg) = NULL; if (trace_log_plugin) { MYSQLND_DEBUG * dbg = trace_log_plugin->methods.trace_instance_init(mysqlnd_debug_std_no_trace_funcs TSRMLS_CC); - if (!dbg) { + MYSQLND_DEBUG * trace_alloc = trace_log_plugin->methods.trace_instance_init(NULL TSRMLS_CC); + if (!dbg || !trace_alloc) { return FAILURE; } dbg->m->set_mode(dbg, MYSQLND_G(debug)); + trace_alloc->m->set_mode(trace_alloc, MYSQLND_G(trace_alloc_settings)); MYSQLND_G(dbg) = dbg; + MYSQLND_G(trace_alloc) = trace_alloc; } } return SUCCESS; @@ -324,13 +306,19 @@ static PHP_RINIT_FUNCTION(mysqlnd) */ static PHP_RSHUTDOWN_FUNCTION(mysqlnd) { - MYSQLND_DEBUG *dbg = MYSQLND_G(dbg); + MYSQLND_DEBUG * dbg = MYSQLND_G(dbg); + MYSQLND_DEBUG * trace_alloc = MYSQLND_G(trace_alloc); DBG_ENTER("RSHUTDOWN"); if (dbg) { dbg->m->close(dbg); dbg->m->free_handle(dbg); MYSQLND_G(dbg) = NULL; } + if (trace_alloc) { + trace_alloc->m->close(trace_alloc); + trace_alloc->m->free_handle(trace_alloc); + MYSQLND_G(trace_alloc) = NULL; + } return SUCCESS; } /* }}} */ |