PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/mysqlnd - mysqlnd_wireprotocol.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 857 1141 75.1 %
Date: 2015-09-02 Functions: 48 58 82.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 7                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 2006-2015 The PHP Group                                |
       6             :   +----------------------------------------------------------------------+
       7             :   | This source file is subject to version 3.01 of the PHP license,      |
       8             :   | that is bundled with this package in the file LICENSE, and is        |
       9             :   | available through the world-wide-web at the following url:           |
      10             :   | http://www.php.net/license/3_01.txt                                  |
      11             :   | If you did not receive a copy of the PHP license and are unable to   |
      12             :   | obtain it through the world-wide-web, please send a note to          |
      13             :   | license@php.net so we can mail you a copy immediately.               |
      14             :   +----------------------------------------------------------------------+
      15             :   | Authors: Andrey Hristov <andrey@mysql.com>                           |
      16             :   |          Ulf Wendel <uwendel@mysql.com>                              |
      17             :   |          Georg Richter <georg@mysql.com>                             |
      18             :   +----------------------------------------------------------------------+
      19             : */
      20             : 
      21             : /* $Id$ */
      22             : #include "php.h"
      23             : #include "php_globals.h"
      24             : #include "mysqlnd.h"
      25             : #include "mysqlnd_priv.h"
      26             : #include "mysqlnd_wireprotocol.h"
      27             : #include "mysqlnd_statistics.h"
      28             : #include "mysqlnd_debug.h"
      29             : #include "zend_ini.h"
      30             : 
      31             : #define MYSQLND_SILENT 1
      32             : 
      33             : #define MYSQLND_DUMP_HEADER_N_BODY
      34             : 
      35             : #define PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_size, packet_type_as_text, packet_type) \
      36             :         { \
      37             :                 DBG_INF_FMT("buf=%p size=%u", (buf), (buf_size)); \
      38             :                 if (FAIL == mysqlnd_read_header((conn)->net, &((packet)->header), (conn)->stats, ((conn)->error_info))) {\
      39             :                         CONN_SET_STATE(conn, CONN_QUIT_SENT); \
      40             :                         SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);\
      41             :                         php_error_docref(NULL, E_WARNING, "%s", mysqlnd_server_gone); \
      42             :                         DBG_ERR_FMT("Can't read %s's header", (packet_type_as_text)); \
      43             :                         DBG_RETURN(FAIL);\
      44             :                 }\
      45             :                 if ((buf_size) < (packet)->header.size) { \
      46             :                         DBG_ERR_FMT("Packet buffer %u wasn't big enough %u, %u bytes will be unread", \
      47             :                                                 (buf_size), (packet)->header.size, (packet)->header.size - (buf_size)); \
      48             :                                                 DBG_RETURN(FAIL); \
      49             :                 }\
      50             :                 if (FAIL == conn->net->data->m.receive_ex((conn)->net, (buf), (packet)->header.size, (conn)->stats, ((conn)->error_info))) { \
      51             :                         CONN_SET_STATE(conn, CONN_QUIT_SENT); \
      52             :                         SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);\
      53             :                         php_error_docref(NULL, E_WARNING, "%s", mysqlnd_server_gone); \
      54             :                         DBG_ERR_FMT("Empty '%s' packet body", (packet_type_as_text)); \
      55             :                         DBG_RETURN(FAIL);\
      56             :                 } \
      57             :                 MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats, packet_type_to_statistic_byte_count[packet_type], \
      58             :                                                                                         MYSQLND_HEADER_SIZE + (packet)->header.size, \
      59             :                                                                                         packet_type_to_statistic_packet_count[packet_type], \
      60             :                                                                                         1); \
      61             :         }
      62             : 
      63             : 
      64             : #define BAIL_IF_NO_MORE_DATA \
      65             :         if ((size_t)(p - begin) > packet->header.size) { \
      66             :                 php_error_docref(NULL, E_WARNING, "Premature end of data (mysqlnd_wireprotocol.c:%u)", __LINE__); \
      67             :                 goto premature_end; \
      68             :         } \
      69             : 
      70             : 
      71             : static const char *unknown_sqlstate= "HY000";
      72             : const char * const mysqlnd_empty_string = "";
      73             : 
      74             : /* Used in mysqlnd_debug.c */
      75             : const char mysqlnd_read_header_name[]   = "mysqlnd_read_header";
      76             : const char mysqlnd_read_body_name[]             = "mysqlnd_read_body";
      77             : 
      78             : #define ERROR_MARKER 0xFF
      79             : #define EODATA_MARKER 0xFE
      80             : 
      81             : /* {{{ mysqlnd_command_to_text
      82             :  */
      83             : const char * const mysqlnd_command_to_text[COM_END] =
      84             : {
      85             :   "SLEEP", "QUIT", "INIT_DB", "QUERY", "FIELD_LIST",
      86             :   "CREATE_DB", "DROP_DB", "REFRESH", "SHUTDOWN", "STATISTICS",
      87             :   "PROCESS_INFO", "CONNECT", "PROCESS_KILL", "DEBUG", "PING",
      88             :   "TIME", "DELAYED_INSERT", "CHANGE_USER", "BINLOG_DUMP",
      89             :   "TABLE_DUMP", "CONNECT_OUT", "REGISTER_SLAVE",
      90             :   "STMT_PREPARE", "STMT_EXECUTE", "STMT_SEND_LONG_DATA", "STMT_CLOSE",
      91             :   "STMT_RESET", "SET_OPTION", "STMT_FETCH", "DAEMON", "BINLOG_DUMP_GTID",
      92             :   "RESET_CONNECTION"
      93             : };
      94             : /* }}} */
      95             : 
      96             : 
      97             : 
      98             : static enum_mysqlnd_collected_stats packet_type_to_statistic_byte_count[PROT_LAST] =
      99             : {
     100             :         STAT_LAST,
     101             :         STAT_LAST,
     102             :         STAT_BYTES_RECEIVED_OK,
     103             :         STAT_BYTES_RECEIVED_EOF,
     104             :         STAT_LAST,
     105             :         STAT_BYTES_RECEIVED_RSET_HEADER,
     106             :         STAT_BYTES_RECEIVED_RSET_FIELD_META,
     107             :         STAT_BYTES_RECEIVED_RSET_ROW,
     108             :         STAT_BYTES_RECEIVED_PREPARE_RESPONSE,
     109             :         STAT_BYTES_RECEIVED_CHANGE_USER,
     110             : };
     111             : 
     112             : static enum_mysqlnd_collected_stats packet_type_to_statistic_packet_count[PROT_LAST] =
     113             : {
     114             :         STAT_LAST,
     115             :         STAT_LAST,
     116             :         STAT_PACKETS_RECEIVED_OK,
     117             :         STAT_PACKETS_RECEIVED_EOF,
     118             :         STAT_LAST,
     119             :         STAT_PACKETS_RECEIVED_RSET_HEADER,
     120             :         STAT_PACKETS_RECEIVED_RSET_FIELD_META,
     121             :         STAT_PACKETS_RECEIVED_RSET_ROW,
     122             :         STAT_PACKETS_RECEIVED_PREPARE_RESPONSE,
     123             :         STAT_PACKETS_RECEIVED_CHANGE_USER,
     124             : };
     125             : 
     126             : 
     127             : /* {{{ php_mysqlnd_net_field_length
     128             :    Get next field's length */
     129             : zend_ulong
     130      331833 : php_mysqlnd_net_field_length(zend_uchar **packet)
     131             : {
     132      331833 :         register zend_uchar *p= (zend_uchar *)*packet;
     133             : 
     134      331833 :         if (*p < 251) {
     135      298808 :                 (*packet)++;
     136      298808 :                 return (zend_ulong) *p;
     137             :         }
     138             : 
     139       33025 :         switch (*p) {
     140             :                 case 251:
     141         700 :                         (*packet)++;
     142         700 :                         return MYSQLND_NULL_LENGTH;
     143             :                 case 252:
     144       32306 :                         (*packet) += 3;
     145       32306 :                         return (zend_ulong) uint2korr(p+1);
     146             :                 case 253:
     147          18 :                         (*packet) += 4;
     148          18 :                         return (zend_ulong) uint3korr(p+1);
     149             :                 default:
     150           1 :                         (*packet) += 9;
     151           1 :                         return (zend_ulong) uint4korr(p+1);
     152             :         }
     153             : }
     154             : /* }}} */
     155             : 
     156             : 
     157             : /* {{{ php_mysqlnd_net_field_length_ll
     158             :    Get next field's length */
     159             : uint64_t
     160       49098 : php_mysqlnd_net_field_length_ll(zend_uchar **packet)
     161             : {
     162       49098 :         register zend_uchar *p = (zend_uchar *)*packet;
     163             : 
     164       49098 :         if (*p < 251) {
     165       49088 :                 (*packet)++;
     166       49088 :                 return (uint64_t) *p;
     167             :         }
     168             : 
     169          10 :         switch (*p) {
     170             :                 case 251:
     171           0 :                         (*packet)++;
     172           0 :                         return (uint64_t) MYSQLND_NULL_LENGTH;
     173             :                 case 252:
     174           8 :                         (*packet) += 3;
     175           8 :                         return (uint64_t) uint2korr(p + 1);
     176             :                 case 253:
     177           0 :                         (*packet) += 4;
     178           0 :                         return (uint64_t) uint3korr(p + 1);
     179             :                 default:
     180           2 :                         (*packet) += 9;
     181           2 :                         return (uint64_t) uint8korr(p + 1);
     182             :         }
     183             : }
     184             : /* }}} */
     185             : 
     186             : 
     187             : /* {{{ php_mysqlnd_net_store_length */
     188             : zend_uchar *
     189         657 : php_mysqlnd_net_store_length(zend_uchar *packet, uint64_t length)
     190             : {
     191         657 :         if (length < (uint64_t) L64(251)) {
     192         580 :                 *packet = (zend_uchar) length;
     193         580 :                 return packet + 1;
     194             :         }
     195             : 
     196          77 :         if (length < (uint64_t) L64(65536)) {
     197          73 :                 *packet++ = 252;
     198          73 :                 int2store(packet,(unsigned int) length);
     199          73 :                 return packet + 2;
     200             :         }
     201             : 
     202           4 :         if (length < (uint64_t) L64(16777216)) {
     203           4 :                 *packet++ = 253;
     204           4 :                 int3store(packet,(zend_ulong) length);
     205           4 :                 return packet + 3;
     206             :         }
     207           0 :         *packet++ = 254;
     208           0 :         int8store(packet, length);
     209           0 :         return packet + 8;
     210             : }
     211             : /* }}} */
     212             : 
     213             : 
     214             : /* {{{ php_mysqlnd_net_store_length_size */
     215             : size_t
     216           0 : php_mysqlnd_net_store_length_size(uint64_t length)
     217             : {
     218           0 :         if (length < (uint64_t) L64(251)) {
     219           0 :                 return 1;
     220             :         }
     221           0 :         if (length < (uint64_t) L64(65536)) {
     222           0 :                 return 3;
     223             :         }
     224           0 :         if (length < (uint64_t) L64(16777216)) {
     225           0 :                 return 4;
     226             :         }
     227           0 :         return 9;
     228             : }
     229             : /* }}} */
     230             : 
     231             : 
     232             : /* {{{ php_mysqlnd_read_error_from_line */
     233             : static enum_func_status
     234         858 : php_mysqlnd_read_error_from_line(zend_uchar *buf, size_t buf_len,
     235             :                                                                 char *error, int error_buf_len,
     236             :                                                                 unsigned int *error_no, char *sqlstate)
     237             : {
     238         858 :         zend_uchar *p = buf;
     239         858 :         int error_msg_len= 0;
     240             : 
     241         858 :         DBG_ENTER("php_mysqlnd_read_error_from_line");
     242             : 
     243         858 :         *error_no = CR_UNKNOWN_ERROR;
     244         858 :         memcpy(sqlstate, unknown_sqlstate, MYSQLND_SQLSTATE_LENGTH);
     245             : 
     246         858 :         if (buf_len > 2) {
     247         858 :                 *error_no = uint2korr(p);
     248         858 :                 p+= 2;
     249             :                 /*
     250             :                   sqlstate is following. No need to check for buf_left_len as we checked > 2 above,
     251             :                   if it was >=2 then we would need a check
     252             :                 */
     253         858 :                 if (*p == '#') {
     254         858 :                         ++p;
     255         858 :                         if ((buf_len - (p - buf)) >= MYSQLND_SQLSTATE_LENGTH) {
     256         858 :                                 memcpy(sqlstate, p, MYSQLND_SQLSTATE_LENGTH);
     257         858 :                                 p+= MYSQLND_SQLSTATE_LENGTH;
     258             :                         } else {
     259           0 :                                 goto end;
     260             :                         }
     261             :                 }
     262         858 :                 if ((buf_len - (p - buf)) > 0) {
     263         858 :                         error_msg_len = MIN((int)((buf_len - (p - buf))), (int) (error_buf_len - 1));
     264         858 :                         memcpy(error, p, error_msg_len);
     265             :                 }
     266             :         }
     267             : end:
     268         858 :         sqlstate[MYSQLND_SQLSTATE_LENGTH] = '\0';
     269         858 :         error[error_msg_len]= '\0';
     270             : 
     271         858 :         DBG_RETURN(FAIL);
     272             : }
     273             : /* }}} */
     274             : 
     275             : 
     276             : /* {{{ mysqlnd_read_header */
     277             : static enum_func_status
     278      297753 : mysqlnd_read_header(MYSQLND_NET * net, MYSQLND_PACKET_HEADER * header,
     279             :                                         MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info)
     280             : {
     281             :         zend_uchar buffer[MYSQLND_HEADER_SIZE];
     282             : 
     283      297753 :         DBG_ENTER(mysqlnd_read_header_name);
     284      297753 :         DBG_INF_FMT("compressed=%u", net->data->compressed);
     285      297753 :         if (FAIL == net->data->m.receive_ex(net, buffer, MYSQLND_HEADER_SIZE, conn_stats, error_info)) {
     286           3 :                 DBG_RETURN(FAIL);
     287             :         }
     288             : 
     289      297750 :         header->size = uint3korr(buffer);
     290      297750 :         header->packet_no = uint1korr(buffer + 3);
     291             : 
     292             : #ifdef MYSQLND_DUMP_HEADER_N_BODY
     293      297750 :         DBG_INF_FMT("HEADER: prot_packet_no=%u size=%3u", header->packet_no, header->size);
     294             : #endif
     295      297750 :         MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn_stats,
     296             :                                                         STAT_PROTOCOL_OVERHEAD_IN, MYSQLND_HEADER_SIZE,
     297             :                                                         STAT_PACKETS_RECEIVED, 1);
     298             : 
     299      297750 :         if (net->data->compressed || net->packet_no == header->packet_no) {
     300             :                 /*
     301             :                   Have to increase the number, so we can send correct number back. It will
     302             :                   round at 255 as this is unsigned char. The server needs this for simple
     303             :                   flow control checking.
     304             :                 */
     305      297749 :                 net->packet_no++;
     306      297749 :                 DBG_RETURN(PASS);
     307             :         }
     308             : 
     309           3 :         DBG_ERR_FMT("Logical link: packets out of order. Expected %u received %u. Packet size="MYSQLND_SZ_T_SPEC,
     310           2 :                                 net->packet_no, header->packet_no, header->size);
     311             : 
     312           3 :         php_error(E_WARNING, "Packets out of order. Expected %u received %u. Packet size="MYSQLND_SZ_T_SPEC,
     313           2 :                           net->packet_no, header->packet_no, header->size);
     314           1 :         DBG_RETURN(FAIL);
     315             : }
     316             : /* }}} */
     317             : 
     318             : 
     319             : /* {{{ php_mysqlnd_greet_read */
     320             : static enum_func_status
     321        1676 : php_mysqlnd_greet_read(void * _packet, MYSQLND_CONN_DATA * conn)
     322             : {
     323             :         zend_uchar buf[2048];
     324        1676 :         zend_uchar *p = buf;
     325        1676 :         zend_uchar *begin = buf;
     326        1676 :         zend_uchar *pad_start = NULL;
     327        1676 :         MYSQLND_PACKET_GREET *packet= (MYSQLND_PACKET_GREET *) _packet;
     328             : 
     329        1676 :         DBG_ENTER("php_mysqlnd_greet_read");
     330             : 
     331        1676 :         PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "greeting", PROT_GREET_PACKET);
     332        1676 :         BAIL_IF_NO_MORE_DATA;
     333             : 
     334        1676 :         packet->auth_plugin_data = packet->intern_auth_plugin_data;
     335        1676 :         packet->auth_plugin_data_len = sizeof(packet->intern_auth_plugin_data);
     336             : 
     337        1676 :         if (packet->header.size < sizeof(buf)) {
     338             :                 /*
     339             :                   Null-terminate the string, so strdup can work even if the packets have a string at the end,
     340             :                   which is not ASCIIZ
     341             :                 */
     342        1676 :                 buf[packet->header.size] = '\0';
     343             :         }
     344             : 
     345        1676 :         packet->protocol_version = uint1korr(p);
     346        1676 :         p++;
     347        1676 :         BAIL_IF_NO_MORE_DATA;
     348             : 
     349        1676 :         if (ERROR_MARKER == packet->protocol_version) {
     350           0 :                 php_mysqlnd_read_error_from_line(p, packet->header.size - 1,
     351             :                                                                                  packet->error, sizeof(packet->error),
     352             :                                                                                  &packet->error_no, packet->sqlstate
     353             :                                                                                 );
     354             :                 /*
     355             :                   The server doesn't send sqlstate in the greet packet.
     356             :                   It's a bug#26426 , so we have to set it correctly ourselves.
     357             :                   It's probably "Too many connections, which has SQL state 08004".
     358             :                 */
     359           0 :                 if (packet->error_no == 1040) {
     360           0 :                         memcpy(packet->sqlstate, "08004", MYSQLND_SQLSTATE_LENGTH);
     361             :                 }
     362           0 :                 DBG_RETURN(PASS);
     363             :         }
     364             : 
     365        1676 :         packet->server_version = estrdup((char *)p);
     366        1676 :         p+= strlen(packet->server_version) + 1; /* eat the '\0' */
     367        1676 :         BAIL_IF_NO_MORE_DATA;
     368             : 
     369        1676 :         packet->thread_id = uint4korr(p);
     370        1676 :         p+=4;
     371        1676 :         BAIL_IF_NO_MORE_DATA;
     372             : 
     373        1676 :         memcpy(packet->auth_plugin_data, p, SCRAMBLE_LENGTH_323);
     374        1676 :         p+= SCRAMBLE_LENGTH_323;
     375        1676 :         BAIL_IF_NO_MORE_DATA;
     376             : 
     377             :         /* pad1 */
     378        1676 :         p++;
     379        1676 :         BAIL_IF_NO_MORE_DATA;
     380             : 
     381        1676 :         packet->server_capabilities = uint2korr(p);
     382        1676 :         p+= 2;
     383        1676 :         BAIL_IF_NO_MORE_DATA;
     384             : 
     385        1676 :         packet->charset_no = uint1korr(p);
     386        1676 :         p++;
     387        1676 :         BAIL_IF_NO_MORE_DATA;
     388             : 
     389        1676 :         packet->server_status = uint2korr(p);
     390        1676 :         p+= 2;
     391        1676 :         BAIL_IF_NO_MORE_DATA;
     392             : 
     393             :         /* pad2 */
     394        1676 :         pad_start = p;
     395        1676 :         p+= 13;
     396        1676 :         BAIL_IF_NO_MORE_DATA;
     397             : 
     398        1676 :         if ((size_t) (p - buf) < packet->header.size) {
     399             :                 /* auth_plugin_data is split into two parts */
     400        1676 :                 memcpy(packet->auth_plugin_data + SCRAMBLE_LENGTH_323, p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
     401        1676 :                 p+= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
     402        1676 :                 p++; /* 0x0 at the end of the scramble and thus last byte in the packet in 5.1 and previous */
     403             :         } else {
     404           0 :                 packet->pre41 = TRUE;
     405             :         }
     406             : 
     407             :         /* Is this a 5.5+ server ? */
     408        1676 :         if ((size_t) (p - buf) < packet->header.size) {
     409             :                  /* backtrack one byte, the 0x0 at the end of the scramble in 5.1 and previous */
     410           0 :                 p--;
     411             : 
     412             :         /* Additional 16 bits for server capabilities */
     413           0 :                 packet->server_capabilities |= uint2korr(pad_start) << 16;
     414             :                 /* And a length of the server scramble in one byte */
     415           0 :                 packet->auth_plugin_data_len = uint1korr(pad_start + 2);
     416           0 :                 if (packet->auth_plugin_data_len > SCRAMBLE_LENGTH) {
     417             :                         /* more data*/
     418           0 :                         zend_uchar * new_auth_plugin_data = emalloc(packet->auth_plugin_data_len);
     419           0 :                         if (!new_auth_plugin_data) {
     420           0 :                                 goto premature_end;
     421             :                         }
     422             :                         /* copy what we already have */
     423           0 :                         memcpy(new_auth_plugin_data, packet->auth_plugin_data, SCRAMBLE_LENGTH);
     424             :                         /* add additional scramble data 5.5+ sent us */
     425           0 :                         memcpy(new_auth_plugin_data + SCRAMBLE_LENGTH, p, packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
     426           0 :                         p+= (packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
     427           0 :                         packet->auth_plugin_data = new_auth_plugin_data;
     428             :                 }
     429             :         }
     430             : 
     431        1676 :         if (packet->server_capabilities & CLIENT_PLUGIN_AUTH) {
     432           0 :                 BAIL_IF_NO_MORE_DATA;
     433             :                 /* The server is 5.5.x and supports authentication plugins */
     434           0 :                 packet->auth_protocol = estrdup((char *)p);
     435           0 :                 p+= strlen(packet->auth_protocol) + 1; /* eat the '\0' */
     436             :         }
     437             : 
     438        3352 :         DBG_INF_FMT("proto=%u server=%s thread_id=%u",
     439        1676 :                                 packet->protocol_version, packet->server_version, packet->thread_id);
     440             : 
     441        6704 :         DBG_INF_FMT("server_capabilities=%u charset_no=%u server_status=%i auth_protocol=%s scramble_length=%u",
     442        3352 :                                 packet->server_capabilities, packet->charset_no, packet->server_status,
     443        1676 :                                 packet->auth_protocol? packet->auth_protocol:"n/a", packet->auth_plugin_data_len);
     444             : 
     445        1676 :         DBG_RETURN(PASS);
     446             : premature_end:
     447           0 :         DBG_ERR_FMT("GREET packet %d bytes shorter than expected", p - begin - packet->header.size);
     448           0 :         php_error_docref(NULL, E_WARNING, "GREET packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
     449           0 :                                          p - begin - packet->header.size);
     450           0 :         DBG_RETURN(FAIL);
     451             : }
     452             : /* }}} */
     453             : 
     454             : 
     455             : /* {{{ php_mysqlnd_greet_free_mem */
     456             : static
     457        1688 : void php_mysqlnd_greet_free_mem(void * _packet, zend_bool stack_allocation)
     458             : {
     459        1688 :         MYSQLND_PACKET_GREET *p= (MYSQLND_PACKET_GREET *) _packet;
     460        1688 :         if (p->server_version) {
     461        1676 :                 efree(p->server_version);
     462        1676 :                 p->server_version = NULL;
     463             :         }
     464        1688 :         if (p->auth_plugin_data && p->auth_plugin_data != p->intern_auth_plugin_data) {
     465           0 :                 efree(p->auth_plugin_data);
     466           0 :                 p->auth_plugin_data = NULL;
     467             :         }
     468        1688 :         if (p->auth_protocol) {
     469           0 :                 efree(p->auth_protocol);
     470           0 :                 p->auth_protocol = NULL;
     471             :         }
     472        1688 :         if (!stack_allocation) {
     473        1688 :                 mnd_pefree(p, p->header.persistent);
     474             :         }
     475        1688 : }
     476             : /* }}} */
     477             : 
     478             : 
     479             : #define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + MYSQLND_MAX_ALLOWED_USER_LEN + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 4096)
     480             : 
     481             : /* {{{ php_mysqlnd_auth_write */
     482             : static
     483        1751 : size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn)
     484             : {
     485             :         zend_uchar buffer[AUTH_WRITE_BUFFER_LEN];
     486        1751 :         zend_uchar *p = buffer + MYSQLND_HEADER_SIZE; /* start after the header */
     487             :         int len;
     488        1751 :         MYSQLND_PACKET_AUTH * packet= (MYSQLND_PACKET_AUTH *) _packet;
     489             : 
     490        1751 :         DBG_ENTER("php_mysqlnd_auth_write");
     491             : 
     492        1751 :         if (!packet->is_change_user_packet) {
     493        1676 :                 int4store(p, packet->client_flags);
     494        1676 :                 p+= 4;
     495             : 
     496        1676 :                 int4store(p, packet->max_packet_size);
     497        1676 :                 p+= 4;
     498             : 
     499        1676 :                 int1store(p, packet->charset_no);
     500        1676 :                 p++;
     501             : 
     502        1676 :                 memset(p, 0, 23); /* filler */
     503        1676 :                 p+= 23;
     504             :         }
     505             : 
     506        1751 :         if (packet->send_auth_data || packet->is_change_user_packet) {
     507        1748 :                 len = MIN(strlen(packet->user), MYSQLND_MAX_ALLOWED_USER_LEN);
     508        1748 :                 memcpy(p, packet->user, len);
     509        1748 :                 p+= len;
     510        1748 :                 *p++ = '\0';
     511             : 
     512             :                 /* defensive coding */
     513        1748 :                 if (packet->auth_data == NULL) {
     514           8 :                         packet->auth_data_len = 0;
     515             :                 }
     516        1748 :                 if (packet->auth_data_len > 0xFF) {
     517             :                         const char * const msg = "Authentication data too long. "
     518           0 :                                 "Won't fit into the buffer and will be truncated. Authentication will thus fail";
     519           0 :                         SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, msg);
     520           0 :                         php_error_docref(NULL, E_WARNING, "%s", msg);
     521           0 :                         DBG_RETURN(0);
     522             :                 }
     523             : 
     524        1748 :                 int1store(p, packet->auth_data_len);
     525        1748 :                 ++p;
     526             : /*!!!!! is the buffer big enough ??? */
     527        1748 :                 if (sizeof(buffer) < (packet->auth_data_len + (p - buffer))) {
     528           0 :                         DBG_ERR("the stack buffer was not enough!!");
     529           0 :                         DBG_RETURN(0);
     530             :                 }
     531        1748 :                 if (packet->auth_data_len) {
     532        1740 :                         memcpy(p, packet->auth_data, packet->auth_data_len);
     533        1740 :                         p+= packet->auth_data_len;
     534             :                 }
     535             : 
     536        1748 :                 if (packet->db) {
     537             :                         /* CLIENT_CONNECT_WITH_DB should have been set */
     538        1748 :                         size_t real_db_len = MIN(MYSQLND_MAX_ALLOWED_DB_LEN, packet->db_len);
     539        1748 :                         memcpy(p, packet->db, real_db_len);
     540        1748 :                         p+= real_db_len;
     541        1748 :                         *p++= '\0';
     542           0 :                 } else if (packet->is_change_user_packet) {
     543           0 :                         *p++= '\0';
     544             :                 }
     545             :                 /* no \0 for no DB */
     546             : 
     547        1748 :                 if (packet->is_change_user_packet) {
     548          75 :                         if (packet->charset_no) {
     549          75 :                                 int2store(p, packet->charset_no);
     550          75 :                                 p+= 2;
     551             :                         }
     552             :                 }
     553             : 
     554        1748 :                 if (packet->auth_plugin_name) {
     555        1748 :                         size_t len = MIN(strlen(packet->auth_plugin_name), sizeof(buffer) - (p - buffer) - 1);
     556        1748 :                         memcpy(p, packet->auth_plugin_name, len);
     557        1748 :                         p+= len;
     558        1748 :                         *p++= '\0';
     559             :                 }
     560             : 
     561        1748 :                 if (packet->connect_attr && zend_hash_num_elements(packet->connect_attr)) {
     562           0 :                         size_t ca_payload_len = 0;
     563             : #ifdef OLD_CODE
     564             :                         HashPosition pos_value;
     565             :                         const char ** entry_value;
     566             :                         zend_hash_internal_pointer_reset_ex(packet->connect_attr, &pos_value);
     567             :                         while (SUCCESS == zend_hash_get_current_data_ex(packet->connect_attr, (void **)&entry_value, &pos_value)) {
     568             :                                 char *s_key;
     569             :                                 unsigned int s_len;
     570             :                                 zend_ulong num_key;
     571             :                                 size_t value_len = strlen(*entry_value);
     572             : 
     573             :                                 if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(packet->connect_attr, &s_key, &s_len, &num_key, &pos_value)) {
     574             :                                         ca_payload_len += php_mysqlnd_net_store_length_size(s_len);
     575             :                                         ca_payload_len += s_len;
     576             :                                         ca_payload_len += php_mysqlnd_net_store_length_size(value_len);
     577             :                                         ca_payload_len += value_len;
     578             :                                 }
     579             :                                 zend_hash_move_forward_ex(conn->options->connect_attr, &pos_value);
     580             :                         }
     581             : #else
     582             : 
     583             :                         {
     584             :                                 zend_string * key;
     585             :                                 zval * entry_value;
     586           0 :                                 ZEND_HASH_FOREACH_STR_KEY_VAL(packet->connect_attr, key, entry_value) {
     587           0 :                                         if (key) { /* HASH_KEY_IS_STRING */
     588           0 :                                                 size_t value_len = Z_STRLEN_P(entry_value);
     589             : 
     590           0 :                                                 ca_payload_len += php_mysqlnd_net_store_length_size(ZSTR_LEN(key));
     591           0 :                                                 ca_payload_len += ZSTR_LEN(key);
     592           0 :                                                 ca_payload_len += php_mysqlnd_net_store_length_size(value_len);
     593           0 :                                                 ca_payload_len += value_len;
     594             :                                         }
     595             :                                 } ZEND_HASH_FOREACH_END();
     596             :                         }
     597             : #endif
     598           0 :                         if (sizeof(buffer) >= (ca_payload_len + php_mysqlnd_net_store_length_size(ca_payload_len) + (p - buffer))) {
     599           0 :                                 p = php_mysqlnd_net_store_length(p, ca_payload_len);
     600             : 
     601             : #ifdef OLD_CODE
     602             :                                 zend_hash_internal_pointer_reset_ex(packet->connect_attr, &pos_value);
     603             :                                 while (SUCCESS == zend_hash_get_current_data_ex(packet->connect_attr, (void **)&entry_value, &pos_value)) {
     604             :                                         char *s_key;
     605             :                                         unsigned int s_len;
     606             :                                         zend_ulong num_key;
     607             :                                         size_t value_len = strlen(*entry_value);
     608             :                                         if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(packet->connect_attr, &s_key, &s_len, &num_key, &pos_value)) {
     609             :                                                 /* copy key */
     610             :                                                 p = php_mysqlnd_net_store_length(p, s_len);
     611             :                                                 memcpy(p, s_key, s_len);
     612             :                                                 p+= s_len;
     613             :                                                 /* copy value */
     614             :                                                 p = php_mysqlnd_net_store_length(p, value_len);
     615             :                                                 memcpy(p, *entry_value, value_len);
     616             :                                                 p+= value_len;
     617             :                                         }
     618             :                                         zend_hash_move_forward_ex(conn->options->connect_attr, &pos_value);
     619             :                                 }
     620             : #else
     621             :                                 {
     622             :                                         zend_string * key;
     623             :                                         zval * entry_value;
     624           0 :                                         ZEND_HASH_FOREACH_STR_KEY_VAL(packet->connect_attr, key, entry_value) {
     625           0 :                                                 if (key) { /* HASH_KEY_IS_STRING */
     626           0 :                                                         size_t value_len = Z_STRLEN_P(entry_value);
     627             : 
     628             :                                                         /* copy key */
     629           0 :                                                         p = php_mysqlnd_net_store_length(p, ZSTR_LEN(key));
     630           0 :                                                         memcpy(p, ZSTR_VAL(key), ZSTR_LEN(key));
     631           0 :                                                         p+= ZSTR_LEN(key);
     632             :                                                         /* copy value */
     633           0 :                                                         p = php_mysqlnd_net_store_length(p, value_len);
     634           0 :                                                         memcpy(p, Z_STRVAL_P(entry_value), value_len);
     635           0 :                                                         p+= value_len;
     636             :                                                 }
     637             :                                         } ZEND_HASH_FOREACH_END();
     638             :                                 }
     639             : #endif
     640             :                         } else {
     641             :                                 /* cannot put the data - skip */
     642             :                         }
     643             :                 }
     644             :         }
     645        1751 :         if (packet->is_change_user_packet) {
     646         150 :                 if (PASS != conn->m->simple_command(conn, COM_CHANGE_USER, buffer + MYSQLND_HEADER_SIZE, p - buffer - MYSQLND_HEADER_SIZE,
     647             :                                                                                    PROT_LAST /* the caller will handle the OK packet */,
     648          75 :                                                                                    packet->silent, TRUE)) {
     649           1 :                         DBG_RETURN(0);
     650             :                 }
     651          74 :                 DBG_RETURN(p - buffer - MYSQLND_HEADER_SIZE);
     652             :         } else {
     653        1676 :                 size_t sent = conn->net->data->m.send_ex(conn->net, buffer, p - buffer - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info);
     654        1676 :                 if (!sent) {
     655           0 :                         CONN_SET_STATE(conn, CONN_QUIT_SENT);
     656             :                 }
     657        1676 :                 DBG_RETURN(sent);
     658             :         }
     659             : }
     660             : /* }}} */
     661             : 
     662             : 
     663             : /* {{{ php_mysqlnd_auth_free_mem */
     664             : static
     665        3424 : void php_mysqlnd_auth_free_mem(void * _packet, zend_bool stack_allocation)
     666             : {
     667        3424 :         if (!stack_allocation) {
     668        3424 :                 MYSQLND_PACKET_AUTH * p = (MYSQLND_PACKET_AUTH *) _packet;
     669        3424 :                 mnd_pefree(p, p->header.persistent);
     670             :         }
     671        3424 : }
     672             : /* }}} */
     673             : 
     674             : 
     675             : #define AUTH_RESP_BUFFER_SIZE 2048
     676             : 
     677             : /* {{{ php_mysqlnd_auth_response_read */
     678             : static enum_func_status
     679        1673 : php_mysqlnd_auth_response_read(void * _packet, MYSQLND_CONN_DATA * conn)
     680             : {
     681             :         zend_uchar local_buf[AUTH_RESP_BUFFER_SIZE];
     682        1673 :         size_t buf_len = conn->net->cmd_buffer.buffer? conn->net->cmd_buffer.length: AUTH_RESP_BUFFER_SIZE;
     683        1673 :         zend_uchar *buf = conn->net->cmd_buffer.buffer? (zend_uchar *) conn->net->cmd_buffer.buffer : local_buf;
     684        1673 :         zend_uchar *p = buf;
     685        1673 :         zend_uchar *begin = buf;
     686             :         zend_ulong i;
     687        1673 :         register MYSQLND_PACKET_AUTH_RESPONSE * packet= (MYSQLND_PACKET_AUTH_RESPONSE *) _packet;
     688             : 
     689        1673 :         DBG_ENTER("php_mysqlnd_auth_response_read");
     690             : 
     691             :         /* leave space for terminating safety \0 */
     692        1673 :         buf_len--;
     693        1673 :         PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "OK", PROT_OK_PACKET);
     694        1673 :         BAIL_IF_NO_MORE_DATA;
     695             : 
     696             :         /*
     697             :           zero-terminate the buffer for safety. We are sure there is place for the \0
     698             :           because buf_len is -1 the size of the buffer pointed
     699             :         */
     700        1673 :         buf[packet->header.size] = '\0';
     701             : 
     702             :         /* Should be always 0x0 or ERROR_MARKER for error */
     703        1673 :         packet->response_code = uint1korr(p);
     704        1673 :         p++;
     705        1673 :         BAIL_IF_NO_MORE_DATA;
     706             : 
     707        1673 :         if (ERROR_MARKER == packet->response_code) {
     708          24 :                 php_mysqlnd_read_error_from_line(p, packet->header.size - 1,
     709             :                                                                                  packet->error, sizeof(packet->error),
     710             :                                                                                  &packet->error_no, packet->sqlstate
     711             :                                                                                 );
     712          24 :                 DBG_RETURN(PASS);
     713             :         }
     714        1649 :         if (0xFE == packet->response_code) {
     715             :                 /* Authentication Switch Response */
     716           0 :                 if (packet->header.size > (size_t) (p - buf)) {
     717           0 :                         packet->new_auth_protocol = mnd_pestrdup((char *)p, FALSE);
     718           0 :                         packet->new_auth_protocol_len = strlen(packet->new_auth_protocol);
     719           0 :                         p+= packet->new_auth_protocol_len + 1; /* +1 for the \0 */
     720             : 
     721           0 :                         packet->new_auth_protocol_data_len = packet->header.size - (size_t) (p - buf);
     722           0 :                         if (packet->new_auth_protocol_data_len) {
     723           0 :                                 packet->new_auth_protocol_data = mnd_emalloc(packet->new_auth_protocol_data_len);
     724           0 :                                 memcpy(packet->new_auth_protocol_data, p, packet->new_auth_protocol_data_len);
     725             :                         }
     726           0 :                         DBG_INF_FMT("The server requested switching auth plugin to : %s", packet->new_auth_protocol);
     727           0 :                         DBG_INF_FMT("Server salt : [%d][%.*s]", packet->new_auth_protocol_data_len, packet->new_auth_protocol_data_len, packet->new_auth_protocol_data);
     728             :                 }
     729             :         } else {
     730             :                 /* Everything was fine! */
     731        1649 :                 packet->affected_rows  = php_mysqlnd_net_field_length_ll(&p);
     732        1649 :                 BAIL_IF_NO_MORE_DATA;
     733             : 
     734        1649 :                 packet->last_insert_id = php_mysqlnd_net_field_length_ll(&p);
     735        1649 :                 BAIL_IF_NO_MORE_DATA;
     736             : 
     737        1649 :                 packet->server_status = uint2korr(p);
     738        1649 :                 p+= 2;
     739        1649 :                 BAIL_IF_NO_MORE_DATA;
     740             : 
     741        1649 :                 packet->warning_count = uint2korr(p);
     742        1649 :                 p+= 2;
     743        1649 :                 BAIL_IF_NO_MORE_DATA;
     744             : 
     745             :                 /* There is a message */
     746        1649 :                 if (packet->header.size > (size_t) (p - buf) && (i = php_mysqlnd_net_field_length(&p))) {
     747           0 :                         packet->message_len = MIN(i, buf_len - (p - begin));
     748           0 :                         packet->message = mnd_pestrndup((char *)p, packet->message_len, FALSE);
     749             :                 } else {
     750        1649 :                         packet->message = NULL;
     751        1649 :                         packet->message_len = 0;
     752             :                 }
     753             : 
     754        3298 :                 DBG_INF_FMT("OK packet: aff_rows=%lld last_ins_id=%pd server_status=%u warnings=%u",
     755        1649 :                                         packet->affected_rows, packet->last_insert_id, packet->server_status,
     756        1649 :                                         packet->warning_count);
     757             :         }
     758             : 
     759        1649 :         DBG_RETURN(PASS);
     760             : premature_end:
     761           0 :         DBG_ERR_FMT("OK packet %d bytes shorter than expected", p - begin - packet->header.size);
     762           0 :         php_error_docref(NULL, E_WARNING, "AUTH_RESPONSE packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
     763           0 :                                          p - begin - packet->header.size);
     764           0 :         DBG_RETURN(FAIL);
     765             : }
     766             : /* }}} */
     767             : 
     768             : 
     769             : /* {{{ php_mysqlnd_auth_response_free_mem */
     770             : static void
     771        1673 : php_mysqlnd_auth_response_free_mem(void * _packet, zend_bool stack_allocation)
     772             : {
     773        1673 :         MYSQLND_PACKET_AUTH_RESPONSE * p = (MYSQLND_PACKET_AUTH_RESPONSE *) _packet;
     774        1673 :         if (p->message) {
     775           0 :                 mnd_efree(p->message);
     776           0 :                 p->message = NULL;
     777             :         }
     778        1673 :         if (p->new_auth_protocol) {
     779           0 :                 mnd_efree(p->new_auth_protocol);
     780           0 :                 p->new_auth_protocol = NULL;
     781             :         }
     782        1673 :         p->new_auth_protocol_len = 0;
     783             : 
     784        1673 :         if (p->new_auth_protocol_data) {
     785           0 :                 mnd_efree(p->new_auth_protocol_data);
     786           0 :                 p->new_auth_protocol_data = NULL;
     787             :         }
     788        1673 :         p->new_auth_protocol_data_len = 0;
     789             : 
     790        1673 :         if (!stack_allocation) {
     791        1673 :                 mnd_pefree(p, p->header.persistent);
     792             :         }
     793        1673 : }
     794             : /* }}} */
     795             : 
     796             : 
     797             : /* {{{ php_mysqlnd_change_auth_response_write */
     798             : static size_t
     799           0 : php_mysqlnd_change_auth_response_write(void * _packet, MYSQLND_CONN_DATA * conn)
     800             : {
     801           0 :         MYSQLND_PACKET_CHANGE_AUTH_RESPONSE *packet= (MYSQLND_PACKET_CHANGE_AUTH_RESPONSE *) _packet;
     802           0 :         zend_uchar * buffer = conn->net->cmd_buffer.length >= packet->auth_data_len? conn->net->cmd_buffer.buffer : mnd_emalloc(packet->auth_data_len);
     803           0 :         zend_uchar *p = buffer + MYSQLND_HEADER_SIZE; /* start after the header */
     804             : 
     805           0 :         DBG_ENTER("php_mysqlnd_change_auth_response_write");
     806             : 
     807           0 :         if (packet->auth_data_len) {
     808           0 :                 memcpy(p, packet->auth_data, packet->auth_data_len);
     809           0 :                 p+= packet->auth_data_len;
     810             :         }
     811             : 
     812             :         {
     813           0 :                 size_t sent = conn->net->data->m.send_ex(conn->net, buffer, p - buffer - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info);
     814           0 :                 if (buffer != conn->net->cmd_buffer.buffer) {
     815           0 :                         mnd_efree(buffer);
     816             :                 }
     817           0 :                 if (!sent) {
     818           0 :                         CONN_SET_STATE(conn, CONN_QUIT_SENT);
     819             :                 }
     820           0 :                 DBG_RETURN(sent);
     821             :         }
     822             : }
     823             : /* }}} */
     824             : 
     825             : 
     826             : /* {{{ php_mysqlnd_change_auth_response_free_mem */
     827             : static void
     828           0 : php_mysqlnd_change_auth_response_free_mem(void * _packet, zend_bool stack_allocation)
     829             : {
     830           0 :         if (!stack_allocation) {
     831           0 :                 MYSQLND_PACKET_CHANGE_AUTH_RESPONSE * p = (MYSQLND_PACKET_CHANGE_AUTH_RESPONSE *) _packet;
     832           0 :                 mnd_pefree(p, p->header.persistent);
     833             :         }
     834           0 : }
     835             : /* }}} */
     836             : 
     837             : 
     838             : #define OK_BUFFER_SIZE 2048
     839             : 
     840             : /* {{{ php_mysqlnd_ok_read */
     841             : static enum_func_status
     842          94 : php_mysqlnd_ok_read(void * _packet, MYSQLND_CONN_DATA * conn)
     843             : {
     844             :         zend_uchar local_buf[OK_BUFFER_SIZE];
     845          94 :         size_t buf_len = conn->net->cmd_buffer.buffer? conn->net->cmd_buffer.length : OK_BUFFER_SIZE;
     846          94 :         zend_uchar *buf = conn->net->cmd_buffer.buffer? (zend_uchar *) conn->net->cmd_buffer.buffer : local_buf;
     847          94 :         zend_uchar *p = buf;
     848          94 :         zend_uchar *begin = buf;
     849             :         zend_ulong i;
     850          94 :         register MYSQLND_PACKET_OK *packet= (MYSQLND_PACKET_OK *) _packet;
     851             : 
     852          94 :         DBG_ENTER("php_mysqlnd_ok_read");
     853             : 
     854          94 :         PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "OK", PROT_OK_PACKET);
     855          94 :         BAIL_IF_NO_MORE_DATA;
     856             : 
     857             :         /* Should be always 0x0 or ERROR_MARKER for error */
     858          94 :         packet->field_count = uint1korr(p);
     859          94 :         p++;
     860          94 :         BAIL_IF_NO_MORE_DATA;
     861             : 
     862          94 :         if (ERROR_MARKER == packet->field_count) {
     863           8 :                 php_mysqlnd_read_error_from_line(p, packet->header.size - 1,
     864             :                                                                                  packet->error, sizeof(packet->error),
     865             :                                                                                  &packet->error_no, packet->sqlstate
     866             :                                                                                 );
     867           8 :                 DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status);
     868           8 :                 DBG_RETURN(PASS);
     869             :         }
     870             :         /* Everything was fine! */
     871          86 :         packet->affected_rows  = php_mysqlnd_net_field_length_ll(&p);
     872          86 :         BAIL_IF_NO_MORE_DATA;
     873             : 
     874          86 :         packet->last_insert_id = php_mysqlnd_net_field_length_ll(&p);
     875          86 :         BAIL_IF_NO_MORE_DATA;
     876             : 
     877          86 :         packet->server_status = uint2korr(p);
     878          86 :         p+= 2;
     879          86 :         BAIL_IF_NO_MORE_DATA;
     880             : 
     881          86 :         packet->warning_count = uint2korr(p);
     882          86 :         p+= 2;
     883          86 :         BAIL_IF_NO_MORE_DATA;
     884             : 
     885             :         /* There is a message */
     886          95 :         if (packet->header.size > (size_t) (p - buf) && (i = php_mysqlnd_net_field_length(&p))) {
     887           9 :                 packet->message_len = MIN(i, buf_len - (p - begin));
     888           9 :                 packet->message = mnd_pestrndup((char *)p, packet->message_len, FALSE);
     889             :         } else {
     890          77 :                 packet->message = NULL;
     891          77 :                 packet->message_len = 0;
     892             :         }
     893             : 
     894         172 :         DBG_INF_FMT("OK packet: aff_rows=%lld last_ins_id=%ld server_status=%u warnings=%u",
     895          86 :                                 packet->affected_rows, packet->last_insert_id, packet->server_status,
     896          86 :                                 packet->warning_count);
     897             : 
     898          86 :         BAIL_IF_NO_MORE_DATA;
     899             : 
     900          86 :         DBG_RETURN(PASS);
     901             : premature_end:
     902           0 :         DBG_ERR_FMT("OK packet %d bytes shorter than expected", p - begin - packet->header.size);
     903           0 :         php_error_docref(NULL, E_WARNING, "OK packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
     904           0 :                                          p - begin - packet->header.size);
     905           0 :         DBG_RETURN(FAIL);
     906             : }
     907             : /* }}} */
     908             : 
     909             : 
     910             : /* {{{ php_mysqlnd_ok_free_mem */
     911             : static void
     912          94 : php_mysqlnd_ok_free_mem(void * _packet, zend_bool stack_allocation)
     913             : {
     914          94 :         MYSQLND_PACKET_OK *p= (MYSQLND_PACKET_OK *) _packet;
     915          94 :         if (p->message) {
     916           9 :                 mnd_efree(p->message);
     917           9 :                 p->message = NULL;
     918             :         }
     919          94 :         if (!stack_allocation) {
     920          94 :                 mnd_pefree(p, p->header.persistent);
     921             :         }
     922          94 : }
     923             : /* }}} */
     924             : 
     925             : 
     926             : /* {{{ php_mysqlnd_eof_read */
     927             : static enum_func_status
     928        7737 : php_mysqlnd_eof_read(void * _packet, MYSQLND_CONN_DATA * conn)
     929             : {
     930             :         /*
     931             :           EOF packet is since 4.1 five bytes long,
     932             :           but we can get also an error, make it bigger.
     933             : 
     934             :           Error : error_code + '#' + sqlstate + MYSQLND_ERRMSG_SIZE
     935             :         */
     936        7737 :         MYSQLND_PACKET_EOF *packet= (MYSQLND_PACKET_EOF *) _packet;
     937        7737 :         size_t buf_len = conn->net->cmd_buffer.length;
     938        7737 :         zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer;
     939        7737 :         zend_uchar *p = buf;
     940        7737 :         zend_uchar *begin = buf;
     941             : 
     942        7737 :         DBG_ENTER("php_mysqlnd_eof_read");
     943             : 
     944        7737 :         PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "EOF", PROT_EOF_PACKET);
     945        7737 :         BAIL_IF_NO_MORE_DATA;
     946             : 
     947             :         /* Should be always EODATA_MARKER */
     948        7737 :         packet->field_count = uint1korr(p);
     949        7737 :         p++;
     950        7737 :         BAIL_IF_NO_MORE_DATA;
     951             : 
     952        7737 :         if (ERROR_MARKER == packet->field_count) {
     953           2 :                 php_mysqlnd_read_error_from_line(p, packet->header.size - 1,
     954             :                                                                                  packet->error, sizeof(packet->error),
     955             :                                                                                  &packet->error_no, packet->sqlstate
     956             :                                                                                 );
     957           2 :                 DBG_RETURN(PASS);
     958             :         }
     959             : 
     960             :         /*
     961             :                 4.1 sends 1 byte EOF packet after metadata of
     962             :                 PREPARE/EXECUTE but 5 bytes after the result. This is not
     963             :                 according to the Docs@Forge!!!
     964             :         */
     965        7735 :         if (packet->header.size > 1) {
     966        7735 :                 packet->warning_count = uint2korr(p);
     967        7735 :                 p+= 2;
     968        7735 :                 BAIL_IF_NO_MORE_DATA;
     969             : 
     970        7735 :                 packet->server_status = uint2korr(p);
     971        7735 :                 p+= 2;
     972        7735 :                 BAIL_IF_NO_MORE_DATA;
     973             :         } else {
     974           0 :                 packet->warning_count = 0;
     975           0 :                 packet->server_status = 0;
     976             :         }
     977             : 
     978        7735 :         BAIL_IF_NO_MORE_DATA;
     979             : 
     980       23205 :         DBG_INF_FMT("EOF packet: fields=%u status=%u warnings=%u",
     981       23205 :                                 packet->field_count, packet->server_status, packet->warning_count);
     982             : 
     983        7735 :         DBG_RETURN(PASS);
     984             : premature_end:
     985           0 :         DBG_ERR_FMT("EOF packet %d bytes shorter than expected", p - begin - packet->header.size);
     986           0 :         php_error_docref(NULL, E_WARNING, "EOF packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
     987           0 :                                          p - begin - packet->header.size);
     988           0 :         DBG_RETURN(FAIL);
     989             : }
     990             : /* }}} */
     991             : 
     992             : 
     993             : /* {{{ php_mysqlnd_eof_free_mem */
     994             : static
     995        7737 : void php_mysqlnd_eof_free_mem(void * _packet, zend_bool stack_allocation)
     996             : {
     997        7737 :         if (!stack_allocation) {
     998        7737 :                 mnd_pefree(_packet, ((MYSQLND_PACKET_EOF *)_packet)->header.persistent);
     999             :         }
    1000        7737 : }
    1001             : /* }}} */
    1002             : 
    1003             : 
    1004             : /* {{{ php_mysqlnd_cmd_write */
    1005       38299 : size_t php_mysqlnd_cmd_write(void * _packet, MYSQLND_CONN_DATA * conn)
    1006             : {
    1007             :         /* Let's have some space, which we can use, if not enough, we will allocate new buffer */
    1008       38299 :         MYSQLND_PACKET_COMMAND * packet= (MYSQLND_PACKET_COMMAND *) _packet;
    1009       38299 :         MYSQLND_NET * net = conn->net;
    1010       38299 :         unsigned int error_reporting = EG(error_reporting);
    1011       38299 :         size_t sent = 0;
    1012             : 
    1013       38299 :         DBG_ENTER("php_mysqlnd_cmd_write");
    1014             :         /*
    1015             :           Reset packet_no, or we will get bad handshake!
    1016             :           Every command starts a new TX and packet numbers are reset to 0.
    1017             :         */
    1018       38299 :         net->packet_no = 0;
    1019       38299 :         net->compressed_envelope_packet_no = 0; /* this is for the response */
    1020             : 
    1021       38299 :         if (error_reporting) {
    1022       37814 :                 EG(error_reporting) = 0;
    1023             :         }
    1024             : 
    1025       38299 :         MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_PACKETS_SENT_CMD);
    1026             : 
    1027             : #ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND
    1028             :         net->data->m.consume_uneaten_data(net, packet->command);
    1029             : #endif
    1030             : 
    1031       39977 :         if (!packet->argument || !packet->arg_len) {
    1032             :                 zend_uchar buffer[MYSQLND_HEADER_SIZE + 1];
    1033             : 
    1034        1678 :                 int1store(buffer + MYSQLND_HEADER_SIZE, packet->command);
    1035        1678 :                 sent = net->data->m.send_ex(net, buffer, 1, conn->stats, conn->error_info);
    1036             :         } else {
    1037       36621 :                 size_t tmp_len = packet->arg_len + 1 + MYSQLND_HEADER_SIZE;
    1038             :                 zend_uchar *tmp, *p;
    1039       36621 :                 tmp = (tmp_len > net->cmd_buffer.length)? mnd_emalloc(tmp_len):net->cmd_buffer.buffer;
    1040       36621 :                 if (!tmp) {
    1041           0 :                         goto end;
    1042             :                 }
    1043       36621 :                 p = tmp + MYSQLND_HEADER_SIZE; /* skip the header */
    1044             : 
    1045       36621 :                 int1store(p, packet->command);
    1046       36621 :                 p++;
    1047             : 
    1048       36621 :                 memcpy(p, packet->argument, packet->arg_len);
    1049             : 
    1050       36621 :                 sent = net->data->m.send_ex(net, tmp, tmp_len - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info);
    1051       36621 :                 if (tmp != net->cmd_buffer.buffer) {
    1052          38 :                         MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CMD_BUFFER_TOO_SMALL);
    1053          38 :                         mnd_efree(tmp);
    1054             :                 }
    1055             :         }
    1056             : end:
    1057       38299 :         if (error_reporting) {
    1058             :                 /* restore error reporting */
    1059       37814 :                 EG(error_reporting) = error_reporting;
    1060             :         }
    1061       38299 :         if (!sent) {
    1062           9 :                 CONN_SET_STATE(conn, CONN_QUIT_SENT);
    1063             :         }
    1064       38299 :         DBG_RETURN(sent);
    1065             : }
    1066             : /* }}} */
    1067             : 
    1068             : 
    1069             : /* {{{ php_mysqlnd_cmd_free_mem */
    1070             : static
    1071       38299 : void php_mysqlnd_cmd_free_mem(void * _packet, zend_bool stack_allocation)
    1072             : {
    1073       38299 :         if (!stack_allocation) {
    1074       38299 :                 MYSQLND_PACKET_COMMAND * p = (MYSQLND_PACKET_COMMAND *) _packet;
    1075       38299 :                 mnd_pefree(p, p->header.persistent);
    1076             :         }
    1077       38299 : }
    1078             : /* }}} */
    1079             : 
    1080             : 
    1081             : /* {{{ php_mysqlnd_rset_header_read */
    1082             : static enum_func_status
    1083       28058 : php_mysqlnd_rset_header_read(void * _packet, MYSQLND_CONN_DATA * conn)
    1084             : {
    1085       28058 :         enum_func_status ret = PASS;
    1086       28058 :         size_t buf_len = conn->net->cmd_buffer.length;
    1087       28058 :         zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer;
    1088       28058 :         zend_uchar *p = buf;
    1089       28058 :         zend_uchar *begin = buf;
    1090             :         size_t len;
    1091       28058 :         MYSQLND_PACKET_RSET_HEADER *packet= (MYSQLND_PACKET_RSET_HEADER *) _packet;
    1092             : 
    1093       28058 :         DBG_ENTER("php_mysqlnd_rset_header_read");
    1094             : 
    1095       28058 :         PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "resultset header", PROT_RSET_HEADER_PACKET);
    1096       28057 :         BAIL_IF_NO_MORE_DATA;
    1097             : 
    1098             :         /*
    1099             :           Don't increment. First byte is ERROR_MARKER on error, but otherwise is starting byte
    1100             :           of encoded sequence for length.
    1101             :         */
    1102       28057 :         if (ERROR_MARKER == *p) {
    1103             :                 /* Error */
    1104         784 :                 p++;
    1105         784 :                 BAIL_IF_NO_MORE_DATA;
    1106         784 :                 php_mysqlnd_read_error_from_line(p, packet->header.size - 1,
    1107             :                                                                                  packet->error_info.error, sizeof(packet->error_info.error),
    1108             :                                                                                  &packet->error_info.error_no, packet->error_info.sqlstate
    1109             :                                                                                 );
    1110         784 :                 DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status);
    1111         784 :                 DBG_RETURN(PASS);
    1112             :         }
    1113             : 
    1114       27273 :         packet->field_count = php_mysqlnd_net_field_length(&p);
    1115       27273 :         BAIL_IF_NO_MORE_DATA;
    1116             : 
    1117       27272 :         switch (packet->field_count) {
    1118             :                 case MYSQLND_NULL_LENGTH:
    1119           9 :                         DBG_INF("LOAD LOCAL");
    1120             :                         /*
    1121             :                           First byte in the packet is the field count.
    1122             :                           Thus, the name is size - 1. And we add 1 for a trailing \0.
    1123             :                           Because we have BAIL_IF_NO_MORE_DATA before the switch, we are guaranteed
    1124             :                           that packet->header.size is > 0. Which means that len can't underflow, that
    1125             :                           would lead to 0 byte allocation but 2^32 or 2^64 bytes copied.
    1126             :                         */
    1127           9 :                         len = packet->header.size - 1;
    1128           9 :                         packet->info_or_local_file = mnd_emalloc(len + 1);
    1129           9 :                         if (packet->info_or_local_file) {
    1130           9 :                                 memcpy(packet->info_or_local_file, p, len);
    1131           9 :                                 packet->info_or_local_file[len] = '\0';
    1132           9 :                                 packet->info_or_local_file_len = len;
    1133             :                         } else {
    1134           0 :                                 SET_OOM_ERROR(*conn->error_info);
    1135           0 :                                 ret = FAIL;
    1136             :                         }
    1137           9 :                         break;
    1138             :                 case 0x00:
    1139       22814 :                         DBG_INF("UPSERT");
    1140       22814 :                         packet->affected_rows = php_mysqlnd_net_field_length_ll(&p);
    1141       22814 :                         BAIL_IF_NO_MORE_DATA;
    1142             : 
    1143       22814 :                         packet->last_insert_id = php_mysqlnd_net_field_length_ll(&p);
    1144       22814 :                         BAIL_IF_NO_MORE_DATA;
    1145             : 
    1146       22814 :                         packet->server_status = uint2korr(p);
    1147       22814 :                         p+=2;
    1148       22814 :                         BAIL_IF_NO_MORE_DATA;
    1149             : 
    1150       22814 :                         packet->warning_count = uint2korr(p);
    1151       22814 :                         p+=2;
    1152       22814 :                         BAIL_IF_NO_MORE_DATA;
    1153             :                         /* Check for additional textual data */
    1154       22814 :                         if (packet->header.size  > (size_t) (p - buf) && (len = php_mysqlnd_net_field_length(&p))) {
    1155         343 :                                 packet->info_or_local_file = mnd_emalloc(len + 1);
    1156         343 :                                 if (packet->info_or_local_file) {
    1157         343 :                                         memcpy(packet->info_or_local_file, p, len);
    1158         343 :                                         packet->info_or_local_file[len] = '\0';
    1159         343 :                                         packet->info_or_local_file_len = len;
    1160             :                                 } else {
    1161           0 :                                         SET_OOM_ERROR(*conn->error_info);
    1162           0 :                                         ret = FAIL;
    1163             :                                 }
    1164             :                         }
    1165       45628 :                         DBG_INF_FMT("affected_rows=%llu last_insert_id=%llu server_status=%u warning_count=%u",
    1166             :                                                 packet->affected_rows, packet->last_insert_id,
    1167       45628 :                                                 packet->server_status, packet->warning_count);
    1168       22814 :                         break;
    1169             :                 default:
    1170        4449 :                         DBG_INF("SELECT");
    1171             :                         /* Result set */
    1172             :                         break;
    1173             :         }
    1174       27272 :         BAIL_IF_NO_MORE_DATA;
    1175             : 
    1176       27272 :         DBG_RETURN(ret);
    1177             : premature_end:
    1178           1 :         DBG_ERR_FMT("RSET_HEADER packet %d bytes shorter than expected", p - begin - packet->header.size);
    1179           1 :         php_error_docref(NULL, E_WARNING, "RSET_HEADER packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
    1180           1 :                                          p - begin - packet->header.size);
    1181           1 :         DBG_RETURN(FAIL);
    1182             : }
    1183             : /* }}} */
    1184             : 
    1185             : 
    1186             : /* {{{ php_mysqlnd_rset_header_free_mem */
    1187             : static
    1188       28058 : void php_mysqlnd_rset_header_free_mem(void * _packet, zend_bool stack_allocation)
    1189             : {
    1190       28058 :         MYSQLND_PACKET_RSET_HEADER *p= (MYSQLND_PACKET_RSET_HEADER *) _packet;
    1191       28058 :         DBG_ENTER("php_mysqlnd_rset_header_free_mem");
    1192       28058 :         if (p->info_or_local_file) {
    1193         352 :                 mnd_efree(p->info_or_local_file);
    1194         352 :                 p->info_or_local_file = NULL;
    1195             :         }
    1196       28058 :         if (!stack_allocation) {
    1197       28058 :                 mnd_pefree(p, p->header.persistent);
    1198             :         }
    1199       28058 :         DBG_VOID_RETURN;
    1200             : }
    1201             : /* }}} */
    1202             : 
    1203             : static size_t rset_field_offsets[] =
    1204             : {
    1205             :         STRUCT_OFFSET(MYSQLND_FIELD, catalog),
    1206             :         STRUCT_OFFSET(MYSQLND_FIELD, catalog_length),
    1207             :         STRUCT_OFFSET(MYSQLND_FIELD, db),
    1208             :         STRUCT_OFFSET(MYSQLND_FIELD, db_length),
    1209             :         STRUCT_OFFSET(MYSQLND_FIELD, table),
    1210             :         STRUCT_OFFSET(MYSQLND_FIELD, table_length),
    1211             :         STRUCT_OFFSET(MYSQLND_FIELD, org_table),
    1212             :         STRUCT_OFFSET(MYSQLND_FIELD, org_table_length),
    1213             :         STRUCT_OFFSET(MYSQLND_FIELD, name),
    1214             :         STRUCT_OFFSET(MYSQLND_FIELD, name_length),
    1215             :         STRUCT_OFFSET(MYSQLND_FIELD, org_name),
    1216             :         STRUCT_OFFSET(MYSQLND_FIELD, org_name_length),
    1217             : };
    1218             : 
    1219             : 
    1220             : /* {{{ php_mysqlnd_rset_field_read */
    1221             : static enum_func_status
    1222      157738 : php_mysqlnd_rset_field_read(void * _packet, MYSQLND_CONN_DATA * conn)
    1223             : {
    1224             :         /* Should be enough for the metadata of a single row */
    1225      157738 :         MYSQLND_PACKET_RES_FIELD *packet = (MYSQLND_PACKET_RES_FIELD *) _packet;
    1226      157738 :         size_t buf_len = conn->net->cmd_buffer.length, total_len = 0;
    1227      157738 :         zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer;
    1228      157738 :         zend_uchar *p = buf;
    1229      157738 :         zend_uchar *begin = buf;
    1230             :         char *root_ptr;
    1231             :         zend_ulong len;
    1232             :         MYSQLND_FIELD *meta;
    1233      157738 :         unsigned int i, field_count = sizeof(rset_field_offsets)/sizeof(size_t);
    1234             : 
    1235      157738 :         DBG_ENTER("php_mysqlnd_rset_field_read");
    1236             : 
    1237      157738 :         PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "field", PROT_RSET_FLD_PACKET);
    1238             : 
    1239      157738 :         if (packet->skip_parsing) {
    1240      134414 :                 DBG_RETURN(PASS);
    1241             :         }
    1242             : 
    1243       23324 :         BAIL_IF_NO_MORE_DATA;
    1244       23324 :         if (ERROR_MARKER == *p) {
    1245             :                 /* Error */
    1246           0 :                 p++;
    1247           0 :                 BAIL_IF_NO_MORE_DATA;
    1248           0 :                 php_mysqlnd_read_error_from_line(p, packet->header.size - 1,
    1249             :                                                                                  packet->error_info.error, sizeof(packet->error_info.error),
    1250             :                                                                                  &packet->error_info.error_no, packet->error_info.sqlstate
    1251             :                                                                                 );
    1252           0 :                 DBG_ERR_FMT("Server error : (%u) %s", packet->error_info.error_no, packet->error_info.error);
    1253           0 :                 DBG_RETURN(PASS);
    1254       23324 :         } else if (EODATA_MARKER == *p && packet->header.size < 8) {
    1255             :                 /* Premature EOF. That should be COM_FIELD_LIST */
    1256           0 :                 DBG_INF("Premature EOF. That should be COM_FIELD_LIST");
    1257           0 :                 packet->stupid_list_fields_eof = TRUE;
    1258           0 :                 DBG_RETURN(PASS);
    1259             :         }
    1260             : 
    1261       23324 :         meta = packet->metadata;
    1262             : 
    1263      163268 :         for (i = 0; i < field_count; i += 2) {
    1264      139944 :                 len = php_mysqlnd_net_field_length(&p);
    1265      139944 :                 BAIL_IF_NO_MORE_DATA;
    1266      139944 :                 switch ((len)) {
    1267             :                         case 0:
    1268       23062 :                                 *(const char **)(((char*)meta) + rset_field_offsets[i]) = mysqlnd_empty_string;
    1269       23062 :                                 *(unsigned int *)(((char*)meta) + rset_field_offsets[i+1]) = 0;
    1270       23062 :                                 break;
    1271             :                         case MYSQLND_NULL_LENGTH:
    1272           0 :                                 goto faulty_or_fake;
    1273             :                         default:
    1274      116882 :                                 *(const char **)(((char *)meta) + rset_field_offsets[i]) = (const char *)p;
    1275      116882 :                                 *(unsigned int *)(((char*)meta) + rset_field_offsets[i+1]) = len;
    1276      116882 :                                 p += len;
    1277      116882 :                                 total_len += len + 1;
    1278             :                                 break;
    1279             :                 }
    1280      139944 :                 BAIL_IF_NO_MORE_DATA;
    1281             :         }
    1282             : 
    1283             :         /* 1 byte length */
    1284       23324 :         if (12 != *p) {
    1285           0 :                 DBG_ERR_FMT("Protocol error. Server sent false length. Expected 12 got %d", (int) *p);
    1286           0 :                 php_error_docref(NULL, E_WARNING, "Protocol error. Server sent false length. Expected 12");
    1287             :         }
    1288             : 
    1289       23324 :         p++;
    1290       23324 :         BAIL_IF_NO_MORE_DATA;
    1291             : 
    1292       23324 :         meta->charsetnr = uint2korr(p);
    1293       23324 :         p += 2;
    1294       23324 :         BAIL_IF_NO_MORE_DATA;
    1295             : 
    1296       23324 :         meta->length = uint4korr(p);
    1297       23324 :         p += 4;
    1298       23324 :         BAIL_IF_NO_MORE_DATA;
    1299             : 
    1300       23324 :         meta->type = uint1korr(p);
    1301       23324 :         p += 1;
    1302       23324 :         BAIL_IF_NO_MORE_DATA;
    1303             : 
    1304       23324 :         meta->flags = uint2korr(p);
    1305       23324 :         p += 2;
    1306       23324 :         BAIL_IF_NO_MORE_DATA;
    1307             : 
    1308       23324 :         meta->decimals = uint1korr(p);
    1309       23324 :         p += 1;
    1310       23324 :         BAIL_IF_NO_MORE_DATA;
    1311             : 
    1312             :         /* 2 byte filler */
    1313       23324 :         p +=2;
    1314       23324 :         BAIL_IF_NO_MORE_DATA;
    1315             : 
    1316             :         /* Should we set NUM_FLAG (libmysql does it) ? */
    1317       46927 :         if (
    1318       23324 :                 (meta->type <= MYSQL_TYPE_INT24 &&
    1319       10695 :                         (meta->type != MYSQL_TYPE_TIMESTAMP || meta->length == 14 || meta->length == 8)
    1320       12908 :                 ) || meta->type == MYSQL_TYPE_YEAR)
    1321             :         {
    1322       10459 :                 meta->flags |= NUM_FLAG;
    1323             :         }
    1324             : 
    1325             : 
    1326             :         /*
    1327             :           def could be empty, thus don't allocate on the root.
    1328             :           NULL_LENGTH (0xFB) comes from COM_FIELD_LIST when the default value is NULL.
    1329             :           Otherwise the string is length encoded.
    1330             :         */
    1331       23324 :         if (packet->header.size > (size_t) (p - buf) &&
    1332           0 :                 (len = php_mysqlnd_net_field_length(&p)) &&
    1333             :                 len != MYSQLND_NULL_LENGTH)
    1334             :         {
    1335           0 :                 BAIL_IF_NO_MORE_DATA;
    1336           0 :                 DBG_INF_FMT("Def found, length %lu, persistent=%u", len, packet->persistent_alloc);
    1337           0 :                 meta->def = mnd_pemalloc(len + 1, packet->persistent_alloc);
    1338           0 :                 if (!meta->def) {
    1339           0 :                         SET_OOM_ERROR(*conn->error_info);
    1340           0 :                         DBG_RETURN(FAIL);
    1341             :                 }
    1342           0 :                 memcpy(meta->def, p, len);
    1343           0 :                 meta->def[len] = '\0';
    1344           0 :                 meta->def_length = len;
    1345           0 :                 p += len;
    1346             :         }
    1347             : 
    1348       23324 :         root_ptr = meta->root = mnd_pemalloc(total_len, packet->persistent_alloc);
    1349       23324 :         if (!root_ptr) {
    1350           0 :                 SET_OOM_ERROR(*conn->error_info);
    1351           0 :                 DBG_RETURN(FAIL);
    1352             :         }
    1353             : 
    1354       23324 :         meta->root_len = total_len;
    1355             : 
    1356       23324 :         if (meta->name != mysqlnd_empty_string) {
    1357       46632 :                 meta->sname = zend_string_init(meta->name, meta->name_length, packet->persistent_alloc);
    1358             :         } else {
    1359           8 :                 meta->sname = ZSTR_EMPTY_ALLOC();
    1360             :         }
    1361       23324 :         meta->name = ZSTR_VAL(meta->sname);
    1362       23324 :         meta->name_length = ZSTR_LEN(meta->sname);
    1363             : 
    1364             :         /* Now do allocs */
    1365       23324 :         if (meta->catalog && meta->catalog != mysqlnd_empty_string) {
    1366       23324 :                 len = meta->catalog_length;
    1367       23324 :                 meta->catalog = memcpy(root_ptr, meta->catalog, len);
    1368       23324 :                 *(root_ptr +=len) = '\0';
    1369       23324 :                 root_ptr++;
    1370             :         }
    1371             : 
    1372       23324 :         if (meta->db && meta->db != mysqlnd_empty_string) {
    1373       17429 :                 len = meta->db_length;
    1374       17429 :                 meta->db = memcpy(root_ptr, meta->db, len);
    1375       17429 :                 *(root_ptr +=len) = '\0';
    1376       17429 :                 root_ptr++;
    1377             :         }
    1378             : 
    1379       23324 :         if (meta->table && meta->table != mysqlnd_empty_string) {
    1380       17674 :                 len = meta->table_length;
    1381       17674 :                 meta->table = memcpy(root_ptr, meta->table, len);
    1382       17674 :                 *(root_ptr +=len) = '\0';
    1383       17674 :                 root_ptr++;
    1384             :         }
    1385             : 
    1386       23324 :         if (meta->org_table && meta->org_table != mysqlnd_empty_string) {
    1387       17429 :                 len = meta->org_table_length;
    1388       17429 :                 meta->org_table = memcpy(root_ptr, meta->org_table, len);
    1389       17429 :                 *(root_ptr +=len) = '\0';
    1390       17429 :                 root_ptr++;
    1391             :         }
    1392             : 
    1393       23324 :         if (meta->org_name && meta->org_name != mysqlnd_empty_string) {
    1394       17710 :                 len = meta->org_name_length;
    1395       17710 :                 meta->org_name = memcpy(root_ptr, meta->org_name, len);
    1396       17710 :                 *(root_ptr +=len) = '\0';
    1397       17710 :                 root_ptr++;
    1398             :         }
    1399             : 
    1400       23324 :         DBG_INF_FMT("allocing root. persistent=%u", packet->persistent_alloc);
    1401             : 
    1402       23324 :         DBG_INF_FMT("FIELD=[%s.%s.%s]", meta->db? meta->db:"*NA*", meta->table? meta->table:"*NA*",
    1403       23324 :                                 meta->name? meta->name:"*NA*");
    1404             : 
    1405       23324 :         DBG_RETURN(PASS);
    1406             : 
    1407             : faulty_or_fake:
    1408           0 :         DBG_ERR_FMT("Protocol error. Server sent NULL_LENGTH. The server is faulty");
    1409           0 :         php_error_docref(NULL, E_WARNING, "Protocol error. Server sent NULL_LENGTH."
    1410             :                                          " The server is faulty");
    1411           0 :         DBG_RETURN(FAIL);
    1412             : premature_end:
    1413           0 :         DBG_ERR_FMT("RSET field packet %d bytes shorter than expected", p - begin - packet->header.size);
    1414           0 :         php_error_docref(NULL, E_WARNING, "Result set field packet "MYSQLND_SZ_T_SPEC" bytes "
    1415           0 :                                         "shorter than expected", p - begin - packet->header.size);
    1416           0 :         DBG_RETURN(FAIL);
    1417             : }
    1418             : /* }}} */
    1419             : 
    1420             : 
    1421             : /* {{{ php_mysqlnd_rset_field_free_mem */
    1422             : static
    1423        7703 : void php_mysqlnd_rset_field_free_mem(void * _packet, zend_bool stack_allocation)
    1424             : {
    1425        7703 :         MYSQLND_PACKET_RES_FIELD *p = (MYSQLND_PACKET_RES_FIELD *) _packet;
    1426             :         /* p->metadata was passed to us as temporal buffer */
    1427        7703 :         if (!stack_allocation) {
    1428        7703 :                 mnd_pefree(p, p->header.persistent);
    1429             :         }
    1430        7703 : }
    1431             : /* }}} */
    1432             : 
    1433             : 
    1434             : /* {{{ php_mysqlnd_read_row_ex */
    1435             : static enum_func_status
    1436       96440 : php_mysqlnd_read_row_ex(MYSQLND_CONN_DATA * conn, MYSQLND_MEMORY_POOL * result_set_memory_pool,
    1437             :                                                 MYSQLND_MEMORY_POOL_CHUNK ** buffer,
    1438             :                                                 size_t * data_size, zend_bool persistent_alloc,
    1439             :                                                 unsigned int prealloc_more_bytes)
    1440             : {
    1441       96440 :         enum_func_status ret = PASS;
    1442             :         MYSQLND_PACKET_HEADER header;
    1443       96440 :         zend_uchar * p = NULL;
    1444       96440 :         zend_bool first_iteration = TRUE;
    1445             : 
    1446       96440 :         DBG_ENTER("php_mysqlnd_read_row_ex");
    1447             : 
    1448             :         /*
    1449             :           To ease the process the server splits everything in packets up to 2^24 - 1.
    1450             :           Even in the case the payload is evenly divisible by this value, the last
    1451             :           packet will be empty, namely 0 bytes. Thus, we can read every packet and ask
    1452             :           for next one if they have 2^24 - 1 sizes. But just read the header of a
    1453             :           zero-length byte, don't read the body, there is no such.
    1454             :         */
    1455             : 
    1456       96440 :         *data_size = prealloc_more_bytes;
    1457             :         while (1) {
    1458       96440 :                 if (FAIL == mysqlnd_read_header(conn->net, &header, conn->stats, conn->error_info)) {
    1459           2 :                         ret = FAIL;
    1460           2 :                         break;
    1461             :                 }
    1462             : 
    1463       96438 :                 *data_size += header.size;
    1464             : 
    1465       96438 :                 if (first_iteration) {
    1466       96438 :                         first_iteration = FALSE;
    1467       96438 :                         *buffer = result_set_memory_pool->get_chunk(result_set_memory_pool, *data_size);
    1468       96438 :                         if (!*buffer) {
    1469           0 :                                 ret = FAIL;
    1470           0 :                                 break;
    1471             :                         }
    1472       96438 :                         p = (*buffer)->ptr;
    1473           0 :                 } else if (!first_iteration) {
    1474             :                         /* Empty packet after MYSQLND_MAX_PACKET_SIZE packet. That's ok, break */
    1475           0 :                         if (!header.size) {
    1476           0 :                                 break;
    1477             :                         }
    1478             : 
    1479             :                         /*
    1480             :                           We have to realloc the buffer.
    1481             :                         */
    1482           0 :                         if (FAIL == (*buffer)->resize_chunk((*buffer), *data_size)) {
    1483           0 :                                 SET_OOM_ERROR(*conn->error_info);
    1484           0 :                                 ret = FAIL;
    1485           0 :                                 break;
    1486             :                         }
    1487             :                         /* The position could have changed, recalculate */
    1488           0 :                         p = (*buffer)->ptr + (*data_size - header.size);
    1489             :                 }
    1490             : 
    1491       96438 :                 if (PASS != (ret = conn->net->data->m.receive_ex(conn->net, p, header.size, conn->stats, conn->error_info))) {
    1492           0 :                         DBG_ERR("Empty row packet body");
    1493           0 :                         php_error(E_WARNING, "Empty row packet body");
    1494           0 :                         break;
    1495             :                 }
    1496             : 
    1497       96438 :                 if (header.size < MYSQLND_MAX_PACKET_SIZE) {
    1498       96438 :                         break;
    1499             :                 }
    1500           0 :         }
    1501       96440 :         if (ret == FAIL && *buffer) {
    1502           0 :                 (*buffer)->free_chunk((*buffer));
    1503           0 :                 *buffer = NULL;
    1504             :         }
    1505       96440 :         *data_size -= prealloc_more_bytes;
    1506       96440 :         DBG_RETURN(ret);
    1507             : }
    1508             : /* }}} */
    1509             : 
    1510             : 
    1511             : /* {{{ php_mysqlnd_rowp_read_binary_protocol */
    1512             : enum_func_status
    1513       20100 : php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
    1514             :                                                                           unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
    1515             :                                                                           zend_bool as_int_or_float, MYSQLND_STATS * stats)
    1516             : {
    1517             :         unsigned int i;
    1518       20100 :         zend_uchar *p = row_buffer->ptr;
    1519             :         zend_uchar *null_ptr, bit;
    1520             :         zval *current_field, *end_field, *start_field;
    1521             : 
    1522       20100 :         DBG_ENTER("php_mysqlnd_rowp_read_binary_protocol");
    1523             : 
    1524       20100 :         if (!fields) {
    1525           0 :                 DBG_RETURN(FAIL);
    1526             :         }
    1527             : 
    1528       20100 :         end_field = (start_field = fields) + field_count;
    1529             : 
    1530             :         /* skip the first byte, not EODATA_MARKER -> 0x0, status */
    1531       20100 :         p++;
    1532       20100 :         null_ptr= p;
    1533       20100 :         p += (field_count + 9)/8;       /* skip null bits */
    1534       20100 :         bit     = 4;                                    /* first 2 bits are reserved */
    1535             : 
    1536       64296 :         for (i = 0, current_field = start_field; current_field < end_field; current_field++, i++) {
    1537             :                 enum_mysqlnd_collected_stats statistic;
    1538       44196 :                 zend_uchar * orig_p = p;
    1539             : 
    1540      265176 :                 DBG_INF_FMT("Into zval=%p decoding column %u [%s.%s.%s] type=%u field->flags&unsigned=%u flags=%u is_bit=%u",
    1541             :                         current_field, i,
    1542      132588 :                         fields_metadata[i].db, fields_metadata[i].table, fields_metadata[i].name, fields_metadata[i].type,
    1543      132588 :                         fields_metadata[i].flags & UNSIGNED_FLAG, fields_metadata[i].flags, fields_metadata[i].type == MYSQL_TYPE_BIT);
    1544       44196 :                 if (*null_ptr & bit) {
    1545        1153 :                         DBG_INF("It's null");
    1546        1153 :                         ZVAL_NULL(current_field);
    1547        1153 :                         statistic = STAT_BINARY_TYPE_FETCHED_NULL;
    1548             :                 } else {
    1549       43043 :                         enum_mysqlnd_field_types type = fields_metadata[i].type;
    1550       43043 :                         mysqlnd_ps_fetch_functions[type].func(current_field, &fields_metadata[i], 0, &p);
    1551             : 
    1552       43043 :                         if (MYSQLND_G(collect_statistics)) {
    1553       43043 :                                 switch (fields_metadata[i].type) {
    1554           0 :                                         case MYSQL_TYPE_DECIMAL:        statistic = STAT_BINARY_TYPE_FETCHED_DECIMAL; break;
    1555          60 :                                         case MYSQL_TYPE_TINY:           statistic = STAT_BINARY_TYPE_FETCHED_INT8; break;
    1556          43 :                                         case MYSQL_TYPE_SHORT:          statistic = STAT_BINARY_TYPE_FETCHED_INT16; break;
    1557       19072 :                                         case MYSQL_TYPE_LONG:           statistic = STAT_BINARY_TYPE_FETCHED_INT32; break;
    1558         138 :                                         case MYSQL_TYPE_FLOAT:          statistic = STAT_BINARY_TYPE_FETCHED_FLOAT; break;
    1559          61 :                                         case MYSQL_TYPE_DOUBLE:         statistic = STAT_BINARY_TYPE_FETCHED_DOUBLE; break;
    1560           0 :                                         case MYSQL_TYPE_NULL:           statistic = STAT_BINARY_TYPE_FETCHED_NULL; break;
    1561          17 :                                         case MYSQL_TYPE_TIMESTAMP:      statistic = STAT_BINARY_TYPE_FETCHED_TIMESTAMP; break;
    1562        2050 :                                         case MYSQL_TYPE_LONGLONG:       statistic = STAT_BINARY_TYPE_FETCHED_INT64; break;
    1563          28 :                                         case MYSQL_TYPE_INT24:          statistic = STAT_BINARY_TYPE_FETCHED_INT24; break;
    1564          19 :                                         case MYSQL_TYPE_DATE:           statistic = STAT_BINARY_TYPE_FETCHED_DATE; break;
    1565          19 :                                         case MYSQL_TYPE_TIME:           statistic = STAT_BINARY_TYPE_FETCHED_TIME; break;
    1566          19 :                                         case MYSQL_TYPE_DATETIME:       statistic = STAT_BINARY_TYPE_FETCHED_DATETIME; break;
    1567          19 :                                         case MYSQL_TYPE_YEAR:           statistic = STAT_BINARY_TYPE_FETCHED_YEAR; break;
    1568           1 :                                         case MYSQL_TYPE_NEWDATE:        statistic = STAT_BINARY_TYPE_FETCHED_DATE; break;
    1569           0 :                                         case MYSQL_TYPE_VARCHAR:        statistic = STAT_BINARY_TYPE_FETCHED_STRING; break;
    1570        1487 :                                         case MYSQL_TYPE_BIT:            statistic = STAT_BINARY_TYPE_FETCHED_BIT; break;
    1571          61 :                                         case MYSQL_TYPE_NEWDECIMAL:     statistic = STAT_BINARY_TYPE_FETCHED_DECIMAL; break;
    1572           0 :                                         case MYSQL_TYPE_ENUM:           statistic = STAT_BINARY_TYPE_FETCHED_ENUM; break;
    1573           0 :                                         case MYSQL_TYPE_SET:            statistic = STAT_BINARY_TYPE_FETCHED_SET; break;
    1574           0 :                                         case MYSQL_TYPE_TINY_BLOB:      statistic = STAT_BINARY_TYPE_FETCHED_BLOB; break;
    1575           9 :                                         case MYSQL_TYPE_MEDIUM_BLOB:statistic = STAT_BINARY_TYPE_FETCHED_BLOB; break;
    1576           0 :                                         case MYSQL_TYPE_LONG_BLOB:      statistic = STAT_BINARY_TYPE_FETCHED_BLOB; break;
    1577        1164 :                                         case MYSQL_TYPE_BLOB:           statistic = STAT_BINARY_TYPE_FETCHED_BLOB; break;
    1578       18436 :                                         case MYSQL_TYPE_VAR_STRING:     statistic = STAT_BINARY_TYPE_FETCHED_STRING; break;
    1579         292 :                                         case MYSQL_TYPE_STRING:         statistic = STAT_BINARY_TYPE_FETCHED_STRING; break;
    1580          48 :                                         case MYSQL_TYPE_GEOMETRY:       statistic = STAT_BINARY_TYPE_FETCHED_GEOMETRY; break;
    1581           0 :                                         default: statistic = STAT_BINARY_TYPE_FETCHED_OTHER; break;
    1582             :                                 }
    1583             :                         }
    1584             :                 }
    1585      132588 :                 MYSQLND_INC_CONN_STATISTIC_W_VALUE2(stats, statistic, 1,
    1586             :                                                                                 STAT_BYTES_RECEIVED_PURE_DATA_PS,
    1587             :                                                                                 (Z_TYPE_P(current_field) == IS_STRING)?
    1588             :                                                                                         Z_STRLEN_P(current_field) : (p - orig_p));
    1589             : 
    1590       44196 :                 if (!((bit<<=1) & 255)) {
    1591         162 :                         bit = 1;        /* to the following byte */
    1592         162 :                         null_ptr++;
    1593             :                 }
    1594             :         }
    1595             : 
    1596       20100 :         DBG_RETURN(PASS);
    1597             : }
    1598             : /* }}} */
    1599             : 
    1600             : 
    1601             : /* {{{ php_mysqlnd_rowp_read_text_protocol */
    1602             : enum_func_status
    1603       70322 : php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
    1604             :                                                                         unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
    1605             :                                                                         zend_bool as_int_or_float, MYSQLND_STATS * stats)
    1606             : {
    1607             :         unsigned int i;
    1608             :         zval *current_field, *end_field, *start_field;
    1609       70322 :         zend_uchar * p = row_buffer->ptr;
    1610       70322 :         size_t data_size = row_buffer->app;
    1611       70322 :         zend_uchar * bit_area = (zend_uchar*) row_buffer->ptr + data_size + 1; /* we allocate from here */
    1612             : 
    1613       70322 :         DBG_ENTER("php_mysqlnd_rowp_read_text_protocol_aux");
    1614             : 
    1615       70322 :         if (!fields) {
    1616           0 :                 DBG_RETURN(FAIL);
    1617             :         }
    1618             : 
    1619       70322 :         end_field = (start_field = fields) + field_count;
    1620             : 
    1621      213014 :         for (i = 0, current_field = start_field; current_field < end_field; current_field++, i++) {
    1622             :                 /* php_mysqlnd_net_field_length() call should be after *this_field_len_pos = p; */
    1623      142692 :                 zend_ulong len = php_mysqlnd_net_field_length(&p);
    1624             : 
    1625             :                 /* NULL or NOT NULL, this is the question! */
    1626      142692 :                 if (len == MYSQLND_NULL_LENGTH) {
    1627         691 :                         ZVAL_NULL(current_field);
    1628             :                 } else {
    1629             : #if defined(MYSQLND_STRING_TO_INT_CONVERSION)
    1630             :                         struct st_mysqlnd_perm_bind perm_bind =
    1631      142001 :                                         mysqlnd_ps_fetch_functions[fields_metadata[i].type];
    1632             : #endif
    1633      142001 :                         if (MYSQLND_G(collect_statistics)) {
    1634             :                                 enum_mysqlnd_collected_stats statistic;
    1635      142001 :                                 switch (fields_metadata[i].type) {
    1636           0 :                                         case MYSQL_TYPE_DECIMAL:        statistic = STAT_TEXT_TYPE_FETCHED_DECIMAL; break;
    1637          35 :                                         case MYSQL_TYPE_TINY:           statistic = STAT_TEXT_TYPE_FETCHED_INT8; break;
    1638          36 :                                         case MYSQL_TYPE_SHORT:          statistic = STAT_TEXT_TYPE_FETCHED_INT16; break;
    1639       69549 :                                         case MYSQL_TYPE_LONG:           statistic = STAT_TEXT_TYPE_FETCHED_INT32; break;
    1640          32 :                                         case MYSQL_TYPE_FLOAT:          statistic = STAT_TEXT_TYPE_FETCHED_FLOAT; break;
    1641          32 :                                         case MYSQL_TYPE_DOUBLE:         statistic = STAT_TEXT_TYPE_FETCHED_DOUBLE; break;
    1642           0 :                                         case MYSQL_TYPE_NULL:           statistic = STAT_TEXT_TYPE_FETCHED_NULL; break;
    1643          39 :                                         case MYSQL_TYPE_TIMESTAMP:      statistic = STAT_TEXT_TYPE_FETCHED_TIMESTAMP; break;
    1644        1286 :                                         case MYSQL_TYPE_LONGLONG:       statistic = STAT_TEXT_TYPE_FETCHED_INT64; break;
    1645          23 :                                         case MYSQL_TYPE_INT24:          statistic = STAT_TEXT_TYPE_FETCHED_INT24; break;
    1646          13 :                                         case MYSQL_TYPE_DATE:           statistic = STAT_TEXT_TYPE_FETCHED_DATE; break;
    1647          13 :                                         case MYSQL_TYPE_TIME:           statistic = STAT_TEXT_TYPE_FETCHED_TIME; break;
    1648          15 :                                         case MYSQL_TYPE_DATETIME:       statistic = STAT_TEXT_TYPE_FETCHED_DATETIME; break;
    1649          13 :                                         case MYSQL_TYPE_YEAR:           statistic = STAT_TEXT_TYPE_FETCHED_YEAR; break;
    1650           1 :                                         case MYSQL_TYPE_NEWDATE:        statistic = STAT_TEXT_TYPE_FETCHED_DATE; break;
    1651           0 :                                         case MYSQL_TYPE_VARCHAR:        statistic = STAT_TEXT_TYPE_FETCHED_STRING; break;
    1652         463 :                                         case MYSQL_TYPE_BIT:            statistic = STAT_TEXT_TYPE_FETCHED_BIT; break;
    1653          32 :                                         case MYSQL_TYPE_NEWDECIMAL:     statistic = STAT_TEXT_TYPE_FETCHED_DECIMAL; break;
    1654           0 :                                         case MYSQL_TYPE_ENUM:           statistic = STAT_TEXT_TYPE_FETCHED_ENUM; break;
    1655           0 :                                         case MYSQL_TYPE_SET:            statistic = STAT_TEXT_TYPE_FETCHED_SET; break;
    1656           0 :                                         case MYSQL_TYPE_TINY_BLOB:      statistic = STAT_TEXT_TYPE_FETCHED_BLOB; break;
    1657          16 :                                         case MYSQL_TYPE_MEDIUM_BLOB:statistic = STAT_TEXT_TYPE_FETCHED_BLOB; break;
    1658           0 :                                         case MYSQL_TYPE_LONG_BLOB:      statistic = STAT_TEXT_TYPE_FETCHED_BLOB; break;
    1659         163 :                                         case MYSQL_TYPE_BLOB:           statistic = STAT_TEXT_TYPE_FETCHED_BLOB; break;
    1660       18182 :                                         case MYSQL_TYPE_VAR_STRING:     statistic = STAT_TEXT_TYPE_FETCHED_STRING; break;
    1661       52010 :                                         case MYSQL_TYPE_STRING:         statistic = STAT_TEXT_TYPE_FETCHED_STRING; break;
    1662          48 :                                         case MYSQL_TYPE_GEOMETRY:       statistic = STAT_TEXT_TYPE_FETCHED_GEOMETRY; break;
    1663           0 :                                         default: statistic = STAT_TEXT_TYPE_FETCHED_OTHER; break;
    1664             :                                 }
    1665      142001 :                                 MYSQLND_INC_CONN_STATISTIC_W_VALUE2(stats, statistic, 1, STAT_BYTES_RECEIVED_PURE_DATA_TEXT, len);
    1666             :                         }
    1667             : #ifdef MYSQLND_STRING_TO_INT_CONVERSION
    1668      142009 :                         if (as_int_or_float && perm_bind.php_type == IS_LONG) {
    1669           8 :                                 zend_uchar save = *(p + len);
    1670             :                                 /* We have to make it ASCIIZ temporarily */
    1671           8 :                                 *(p + len) = '\0';
    1672           8 :                                 if (perm_bind.pack_len < SIZEOF_ZEND_LONG) {
    1673             :                                         /* direct conversion */
    1674             :                                         int64_t v =
    1675             : #ifndef PHP_WIN32
    1676           6 :                                                 atoll((char *) p);
    1677             : #else
    1678             :                                                 _atoi64((char *) p);
    1679             : #endif
    1680           6 :                                         ZVAL_LONG(current_field, (zend_long) v); /* the cast is safe */
    1681             :                                 } else {
    1682             :                                         uint64_t v =
    1683             : #ifndef PHP_WIN32
    1684           2 :                                                 (uint64_t) atoll((char *) p);
    1685             : #else
    1686             :                                                 (uint64_t) _atoi64((char *) p);
    1687             : #endif
    1688           2 :                                         zend_bool uns = fields_metadata[i].flags & UNSIGNED_FLAG? TRUE:FALSE;
    1689             :                                         /* We have to make it ASCIIZ temporarily */
    1690             : #if SIZEOF_ZEND_LONG==8
    1691           2 :                                         if (uns == TRUE && v > 9223372036854775807L)
    1692             : #elif SIZEOF_ZEND_LONG==4
    1693             :                                         if ((uns == TRUE && v > L64(2147483647)) ||
    1694             :                                                 (uns == FALSE && (( L64(2147483647) < (int64_t) v) ||
    1695             :                                                 (L64(-2147483648) > (int64_t) v))))
    1696             : #else
    1697             : #error Need fix for this architecture
    1698             : #endif /* SIZEOF */
    1699             :                                         {
    1700           0 :                                                 ZVAL_STRINGL(current_field, (char *)p, len);
    1701             :                                         } else {
    1702           2 :                                                 ZVAL_LONG(current_field, (zend_long) v); /* the cast is safe */
    1703             :                                         }
    1704             :                                 }
    1705           8 :                                 *(p + len) = save;
    1706      141995 :                         } else if (as_int_or_float && perm_bind.php_type == IS_DOUBLE) {
    1707           2 :                                 zend_uchar save = *(p + len);
    1708             :                                 /* We have to make it ASCIIZ temporarily */
    1709           2 :                                 *(p + len) = '\0';
    1710           2 :                                 ZVAL_DOUBLE(current_field, atof((char *) p));
    1711           2 :                                 *(p + len) = save;
    1712             :                         } else
    1713             : #endif /* MYSQLND_STRING_TO_INT_CONVERSION */
    1714      141991 :                         if (fields_metadata[i].type == MYSQL_TYPE_BIT) {
    1715             :                                 /*
    1716             :                                   BIT fields are specially handled. As they come as bit mask, we have
    1717             :                                   to convert it to human-readable representation. As the bits take
    1718             :                                   less space in the protocol than the numbers they represent, we don't
    1719             :                                   have enough space in the packet buffer to overwrite inside.
    1720             :                                   Thus, a bit more space is pre-allocated at the end of the buffer,
    1721             :                                   see php_mysqlnd_rowp_read(). And we add the strings at the end.
    1722             :                                   Definitely not nice, _hackish_ :(, but works.
    1723             :                                 */
    1724         462 :                                 zend_uchar *start = bit_area;
    1725         462 :                                 ps_fetch_from_1_to_8_bytes(current_field, &(fields_metadata[i]), 0, &p, len);
    1726             :                                 /*
    1727             :                                   We have advanced in ps_fetch_from_1_to_8_bytes. We should go back because
    1728             :                                   later in this function there will be an advancement.
    1729             :                                 */
    1730         462 :                                 p -= len;
    1731         462 :                                 if (Z_TYPE_P(current_field) == IS_LONG) {
    1732         462 :                                         bit_area += 1 + sprintf((char *)start, ZEND_LONG_FMT, Z_LVAL_P(current_field));
    1733         924 :                                         ZVAL_STRINGL(current_field, (char *) start, bit_area - start - 1);
    1734           0 :                                 } else if (Z_TYPE_P(current_field) == IS_STRING){
    1735           0 :                                         memcpy(bit_area, Z_STRVAL_P(current_field), Z_STRLEN_P(current_field));
    1736           0 :                                         bit_area += Z_STRLEN_P(current_field);
    1737           0 :                                         *bit_area++ = '\0';
    1738             :                                         zval_dtor(current_field);
    1739           0 :                                         ZVAL_STRINGL(current_field, (char *) start, bit_area - start - 1);
    1740             :                                 }
    1741             :                         } else {
    1742      283058 :                                 ZVAL_STRINGL(current_field, (char *)p, len);
    1743             :                         }
    1744      142001 :                         p += len;
    1745             :                 }
    1746             :         }
    1747             : 
    1748       70322 :         DBG_RETURN(PASS);
    1749             : }
    1750             : /* }}} */
    1751             : 
    1752             : 
    1753             : /* {{{ php_mysqlnd_rowp_read_text_protocol_zval */
    1754             : enum_func_status
    1755       70273 : php_mysqlnd_rowp_read_text_protocol_zval(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
    1756             :                                                                         unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
    1757             :                                                                         zend_bool as_int_or_float, MYSQLND_STATS * stats)
    1758             : {
    1759             :         enum_func_status ret;
    1760       70273 :         DBG_ENTER("php_mysqlnd_rowp_read_text_protocol_zval");
    1761       70273 :         ret = php_mysqlnd_rowp_read_text_protocol_aux(row_buffer, fields, field_count, fields_metadata, as_int_or_float, stats);
    1762       70273 :         DBG_RETURN(ret);
    1763             : }
    1764             : /* }}} */
    1765             : 
    1766             : 
    1767             : /* {{{ php_mysqlnd_rowp_read_text_protocol_c */
    1768             : enum_func_status
    1769          49 : php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
    1770             :                                                                         unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
    1771             :                                                                         zend_bool as_int_or_float, MYSQLND_STATS * stats)
    1772             : {
    1773             :         enum_func_status ret;
    1774          49 :         DBG_ENTER("php_mysqlnd_rowp_read_text_protocol_c");
    1775          49 :         ret = php_mysqlnd_rowp_read_text_protocol_aux(row_buffer, fields, field_count, fields_metadata, as_int_or_float, stats);
    1776          49 :         DBG_RETURN(ret);
    1777             : }
    1778             : /* }}} */
    1779             : 
    1780             : 
    1781             : /* {{{ php_mysqlnd_rowp_read */
    1782             : /*
    1783             :   if normal statements => packet->fields is created by this function,
    1784             :   if PS => packet->fields is passed from outside
    1785             : */
    1786             : static enum_func_status
    1787       96440 : php_mysqlnd_rowp_read(void * _packet, MYSQLND_CONN_DATA * conn)
    1788             : {
    1789             :         zend_uchar *p;
    1790       96440 :         enum_func_status ret = PASS;
    1791       96440 :         MYSQLND_PACKET_ROW *packet= (MYSQLND_PACKET_ROW *) _packet;
    1792       96440 :         size_t post_alloc_for_bit_fields = 0;
    1793       96440 :         size_t data_size = 0;
    1794             : 
    1795       96440 :         DBG_ENTER("php_mysqlnd_rowp_read");
    1796             : 
    1797       96440 :         if (!packet->binary_protocol && packet->bit_fields_count) {
    1798             :                 /* For every field we need terminating \0 */
    1799         966 :                 post_alloc_for_bit_fields = packet->bit_fields_total_len + packet->bit_fields_count;
    1800             :         }
    1801             : 
    1802      192880 :         ret = php_mysqlnd_read_row_ex(conn, packet->result_set_memory_pool, &packet->row_buffer, &data_size,
    1803       96440 :                                                                   packet->persistent_alloc, post_alloc_for_bit_fields
    1804             :                                                                  );
    1805       96440 :         if (FAIL == ret) {
    1806           2 :                 goto end;
    1807             :         }
    1808       96438 :         MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats, packet_type_to_statistic_byte_count[PROT_ROW_PACKET],
    1809             :                                                                                 MYSQLND_HEADER_SIZE + packet->header.size,
    1810             :                                                                                 packet_type_to_statistic_packet_count[PROT_ROW_PACKET],
    1811             :                                                                                 1);
    1812             : 
    1813             :         /* packet->row_buffer->ptr is of size 'data_size + 1' */
    1814       96438 :         packet->header.size = data_size;
    1815       96438 :         packet->row_buffer->app = data_size;
    1816             : 
    1817       96438 :         if (ERROR_MARKER == (*(p = packet->row_buffer->ptr))) {
    1818             :                 /*
    1819             :                    Error message as part of the result set,
    1820             :                    not good but we should not hang. See:
    1821             :                    Bug #27876 : SF with cyrillic variable name fails during execution
    1822             :                 */
    1823           0 :                 ret = FAIL;
    1824           0 :                 php_mysqlnd_read_error_from_line(p + 1, data_size - 1,
    1825             :                                                                                  packet->error_info.error,
    1826             :                                                                                  sizeof(packet->error_info.error),
    1827             :                                                                                  &packet->error_info.error_no,
    1828             :                                                                                  packet->error_info.sqlstate
    1829             :                                                                                 );
    1830      100896 :         } else if (EODATA_MARKER == *p && data_size < 8) { /* EOF */
    1831        4458 :                 packet->eof = TRUE;
    1832        4458 :                 p++;
    1833        4458 :                 if (data_size > 1) {
    1834        4458 :                         packet->warning_count = uint2korr(p);
    1835        4458 :                         p += 2;
    1836        4458 :                         packet->server_status = uint2korr(p);
    1837             :                         /* Seems we have 3 bytes reserved for future use */
    1838        4458 :                         DBG_INF_FMT("server_status=%u warning_count=%u", packet->server_status, packet->warning_count);
    1839             :                 }
    1840             :         } else {
    1841       91980 :                 MYSQLND_INC_CONN_STATISTIC(conn->stats,
    1842             :                                                                         packet->binary_protocol? STAT_ROWS_FETCHED_FROM_SERVER_PS:
    1843             :                                                                                                                          STAT_ROWS_FETCHED_FROM_SERVER_NORMAL);
    1844             : 
    1845       91980 :                 packet->eof = FALSE;
    1846             :                 /* packet->field_count is set by the user of the packet */
    1847             : 
    1848       91980 :                 if (!packet->skip_extraction) {
    1849       17700 :                         if (!packet->fields) {
    1850       17700 :                                 DBG_INF("Allocating packet->fields");
    1851             :                                 /*
    1852             :                                   old-API will probably set packet->fields to NULL every time, though for
    1853             :                                   unbuffered sets it makes not much sense as the zvals in this buffer matter,
    1854             :                                   not the buffer. Constantly allocating and deallocating brings nothing.
    1855             : 
    1856             :                                   For PS - if stmt_store() is performed, thus we don't have a cursor, it will
    1857             :                                   behave just like old-API buffered. Cursors will behave like a bit different,
    1858             :                                   but mostly like old-API unbuffered and thus will populate this array with
    1859             :                                   value.
    1860             :                                 */
    1861       17700 :                                 packet->fields = mnd_pecalloc(packet->field_count, sizeof(zval),
    1862             :                                                                                                                 packet->persistent_alloc);
    1863             :                         }
    1864             :                 } else {
    1865       74280 :                         MYSQLND_INC_CONN_STATISTIC(conn->stats,
    1866             :                                                                                 packet->binary_protocol? STAT_ROWS_SKIPPED_PS:
    1867             :                                                                                                                                  STAT_ROWS_SKIPPED_NORMAL);
    1868             :                 }
    1869             :         }
    1870             : 
    1871             : end:
    1872       96440 :         DBG_RETURN(ret);
    1873             : }
    1874             : /* }}} */
    1875             : 
    1876             : 
    1877             : /* {{{ php_mysqlnd_rowp_free_mem */
    1878             : static void
    1879        4443 : php_mysqlnd_rowp_free_mem(void * _packet, zend_bool stack_allocation)
    1880             : {
    1881             :         MYSQLND_PACKET_ROW *p;
    1882             : 
    1883        4443 :         DBG_ENTER("php_mysqlnd_rowp_free_mem");
    1884        4443 :         p = (MYSQLND_PACKET_ROW *) _packet;
    1885        4443 :         if (p->row_buffer) {
    1886        4434 :                 p->row_buffer->free_chunk(p->row_buffer);
    1887        4434 :                 p->row_buffer = NULL;
    1888             :         }
    1889        4443 :         DBG_INF_FMT("stack_allocation=%u persistent=%u", (int)stack_allocation, (int)p->header.persistent);
    1890             :         /*
    1891             :           Don't free packet->fields :
    1892             :           - normal queries -> store_result() | fetch_row_unbuffered() will transfer
    1893             :             the ownership and NULL it.
    1894             :           - PS will pass in it the bound variables, we have to use them! and of course
    1895             :             not free the array. As it is passed to us, we should not clean it ourselves.
    1896             :         */
    1897        4443 :         if (!stack_allocation) {
    1898        4443 :                 mnd_pefree(p, p->header.persistent);
    1899             :         }
    1900        4443 :         DBG_VOID_RETURN;
    1901             : }
    1902             : /* }}} */
    1903             : 
    1904             : 
    1905             : /* {{{ php_mysqlnd_stats_read */
    1906             : static enum_func_status
    1907          15 : php_mysqlnd_stats_read(void * _packet, MYSQLND_CONN_DATA * conn)
    1908             : {
    1909          15 :         MYSQLND_PACKET_STATS *packet= (MYSQLND_PACKET_STATS *) _packet;
    1910          15 :         size_t buf_len = conn->net->cmd_buffer.length;
    1911          15 :         zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer;
    1912             : 
    1913          15 :         DBG_ENTER("php_mysqlnd_stats_read");
    1914             : 
    1915          15 :         PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "statistics", PROT_STATS_PACKET);
    1916             : 
    1917          15 :         packet->message = mnd_emalloc(packet->header.size + 1);
    1918          15 :         memcpy(packet->message, buf, packet->header.size);
    1919          15 :         packet->message[packet->header.size] = '\0';
    1920          15 :         packet->message_len = packet->header.size;
    1921             : 
    1922          15 :         DBG_RETURN(PASS);
    1923             : }
    1924             : /* }}} */
    1925             : 
    1926             : 
    1927             : /* {{{ php_mysqlnd_stats_free_mem */
    1928             : static
    1929          15 : void php_mysqlnd_stats_free_mem(void * _packet, zend_bool stack_allocation)
    1930             : {
    1931          15 :         MYSQLND_PACKET_STATS *p= (MYSQLND_PACKET_STATS *) _packet;
    1932          15 :         if (p->message) {
    1933          15 :                 mnd_efree(p->message);
    1934          15 :                 p->message = NULL;
    1935             :         }
    1936          15 :         if (!stack_allocation) {
    1937          15 :                 mnd_pefree(p, p->header.persistent);
    1938             :         }
    1939          15 : }
    1940             : /* }}} */
    1941             : 
    1942             : 
    1943             : /* 1 + 4 (id) + 2 (field_c) + 2 (param_c) + 1 (filler) + 2 (warnings ) */
    1944             : #define PREPARE_RESPONSE_SIZE_41 9
    1945             : #define PREPARE_RESPONSE_SIZE_50 12
    1946             : 
    1947             : /* {{{ php_mysqlnd_prepare_read */
    1948             : static enum_func_status
    1949        4248 : php_mysqlnd_prepare_read(void * _packet, MYSQLND_CONN_DATA * conn)
    1950             : {
    1951             :         /* In case of an error, we should have place to put it */
    1952        4248 :         size_t buf_len = conn->net->cmd_buffer.length;
    1953        4248 :         zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer;
    1954        4248 :         zend_uchar *p = buf;
    1955        4248 :         zend_uchar *begin = buf;
    1956             :         unsigned int data_size;
    1957        4248 :         MYSQLND_PACKET_PREPARE_RESPONSE *packet= (MYSQLND_PACKET_PREPARE_RESPONSE *) _packet;
    1958             : 
    1959        4248 :         DBG_ENTER("php_mysqlnd_prepare_read");
    1960             : 
    1961        4248 :         PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "prepare", PROT_PREPARE_RESP_PACKET);
    1962        4247 :         BAIL_IF_NO_MORE_DATA;
    1963             : 
    1964        4247 :         data_size = packet->header.size;
    1965        4247 :         packet->error_code = uint1korr(p);
    1966        4247 :         p++;
    1967        4247 :         BAIL_IF_NO_MORE_DATA;
    1968             : 
    1969        4247 :         if (ERROR_MARKER == packet->error_code) {
    1970          26 :                 php_mysqlnd_read_error_from_line(p, data_size - 1,
    1971             :                                                                                  packet->error_info.error,
    1972             :                                                                                  sizeof(packet->error_info.error),
    1973             :                                                                                  &packet->error_info.error_no,
    1974             :                                                                                  packet->error_info.sqlstate
    1975             :                                                                                 );
    1976          26 :                 DBG_RETURN(PASS);
    1977             :         }
    1978             : 
    1979        4221 :         if (data_size != PREPARE_RESPONSE_SIZE_41 &&
    1980             :                 data_size != PREPARE_RESPONSE_SIZE_50 &&
    1981             :                 !(data_size > PREPARE_RESPONSE_SIZE_50)) {
    1982           0 :                 DBG_ERR_FMT("Wrong COM_STMT_PREPARE response size. Received %u", data_size);
    1983           0 :                 php_error(E_WARNING, "Wrong COM_STMT_PREPARE response size. Received %u", data_size);
    1984           0 :                 DBG_RETURN(FAIL);
    1985             :         }
    1986             : 
    1987        4221 :         packet->stmt_id = uint4korr(p);
    1988        4221 :         p += 4;
    1989        4221 :         BAIL_IF_NO_MORE_DATA;
    1990             : 
    1991             :         /* Number of columns in result set */
    1992        4221 :         packet->field_count = uint2korr(p);
    1993        4221 :         p += 2;
    1994        4221 :         BAIL_IF_NO_MORE_DATA;
    1995             : 
    1996        4221 :         packet->param_count = uint2korr(p);
    1997        4221 :         p += 2;
    1998        4221 :         BAIL_IF_NO_MORE_DATA;
    1999             : 
    2000        4221 :         if (data_size > 9) {
    2001             :                 /* 0x0 filler sent by the server for 5.0+ clients */
    2002        4221 :                 p++;
    2003        4221 :                 BAIL_IF_NO_MORE_DATA;
    2004             : 
    2005        4221 :                 packet->warning_count = uint2korr(p);
    2006             :         }
    2007             : 
    2008        4221 :         DBG_INF_FMT("Prepare packet read: stmt_id=%u fields=%u params=%u",
    2009             :                                 packet->stmt_id, packet->field_count, packet->param_count);
    2010             : 
    2011        4221 :         BAIL_IF_NO_MORE_DATA;
    2012             : 
    2013        4221 :         DBG_RETURN(PASS);
    2014             : premature_end:
    2015           0 :         DBG_ERR_FMT("PREPARE packet %d bytes shorter than expected", p - begin - packet->header.size);
    2016           0 :         php_error_docref(NULL, E_WARNING, "PREPARE packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
    2017           0 :                                          p - begin - packet->header.size);
    2018           0 :         DBG_RETURN(FAIL);
    2019             : }
    2020             : /* }}} */
    2021             : 
    2022             : 
    2023             : /* {{{ php_mysqlnd_prepare_free_mem */
    2024             : static void
    2025        4248 : php_mysqlnd_prepare_free_mem(void * _packet, zend_bool stack_allocation)
    2026             : {
    2027        4248 :         MYSQLND_PACKET_PREPARE_RESPONSE *p= (MYSQLND_PACKET_PREPARE_RESPONSE *) _packet;
    2028        4248 :         if (!stack_allocation) {
    2029        4248 :                 mnd_pefree(p, p->header.persistent);
    2030             :         }
    2031        4248 : }
    2032             : /* }}} */
    2033             : 
    2034             : 
    2035             : /* {{{ php_mysqlnd_chg_user_read */
    2036             : static enum_func_status
    2037          74 : php_mysqlnd_chg_user_read(void * _packet, MYSQLND_CONN_DATA * conn)
    2038             : {
    2039             :         /* There could be an error message */
    2040          74 :         size_t buf_len = conn->net->cmd_buffer.length;
    2041          74 :         zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer;
    2042          74 :         zend_uchar *p = buf;
    2043          74 :         zend_uchar *begin = buf;
    2044          74 :         MYSQLND_PACKET_CHG_USER_RESPONSE *packet= (MYSQLND_PACKET_CHG_USER_RESPONSE *) _packet;
    2045             : 
    2046          74 :         DBG_ENTER("php_mysqlnd_chg_user_read");
    2047             : 
    2048          74 :         PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "change user response", PROT_CHG_USER_RESP_PACKET);
    2049          74 :         BAIL_IF_NO_MORE_DATA;
    2050             : 
    2051             :         /*
    2052             :           Don't increment. First byte is ERROR_MARKER on error, but otherwise is starting byte
    2053             :           of encoded sequence for length.
    2054             :         */
    2055             : 
    2056             :         /* Should be always 0x0 or ERROR_MARKER for error */
    2057          74 :         packet->response_code = uint1korr(p);
    2058          74 :         p++;
    2059             : 
    2060          74 :         if (packet->header.size == 1 && buf[0] == EODATA_MARKER && packet->server_capabilities & CLIENT_SECURE_CONNECTION) {
    2061             :                 /* We don't handle 3.23 authentication */
    2062           0 :                 packet->server_asked_323_auth = TRUE;
    2063           0 :                 DBG_RETURN(FAIL);
    2064             :         }
    2065             : 
    2066          74 :         if (ERROR_MARKER == packet->response_code) {
    2067          14 :                 php_mysqlnd_read_error_from_line(p, packet->header.size - 1,
    2068             :                                                                                  packet->error_info.error,
    2069             :                                                                                  sizeof(packet->error_info.error),
    2070             :                                                                                  &packet->error_info.error_no,
    2071             :                                                                                  packet->error_info.sqlstate
    2072             :                                                                                 );
    2073             :         }
    2074          74 :         BAIL_IF_NO_MORE_DATA;
    2075          74 :         if (packet->response_code == 0xFE && packet->header.size > (size_t) (p - buf)) {
    2076           0 :                 packet->new_auth_protocol = mnd_pestrdup((char *)p, FALSE);
    2077           0 :                 packet->new_auth_protocol_len = strlen(packet->new_auth_protocol);
    2078           0 :                 p+= packet->new_auth_protocol_len + 1; /* +1 for the \0 */
    2079           0 :                 packet->new_auth_protocol_data_len = packet->header.size - (size_t) (p - buf);
    2080           0 :                 if (packet->new_auth_protocol_data_len) {
    2081           0 :                         packet->new_auth_protocol_data = mnd_emalloc(packet->new_auth_protocol_data_len);
    2082           0 :                         memcpy(packet->new_auth_protocol_data, p, packet->new_auth_protocol_data_len);
    2083             :                 }
    2084           0 :                 DBG_INF_FMT("The server requested switching auth plugin to : %s", packet->new_auth_protocol);
    2085           0 :                 DBG_INF_FMT("Server salt : [%*s]", packet->new_auth_protocol_data_len, packet->new_auth_protocol_data);
    2086             :         }
    2087             : 
    2088          74 :         DBG_RETURN(PASS);
    2089             : premature_end:
    2090           0 :         DBG_ERR_FMT("CHANGE_USER packet %d bytes shorter than expected", p - begin - packet->header.size);
    2091           0 :         php_error_docref(NULL, E_WARNING, "CHANGE_USER packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
    2092           0 :                                                  p - begin - packet->header.size);
    2093           0 :         DBG_RETURN(FAIL);
    2094             : }
    2095             : /* }}} */
    2096             : 
    2097             : 
    2098             : /* {{{ php_mysqlnd_chg_user_free_mem */
    2099             : static void
    2100          75 : php_mysqlnd_chg_user_free_mem(void * _packet, zend_bool stack_allocation)
    2101             : {
    2102          75 :         MYSQLND_PACKET_CHG_USER_RESPONSE * p = (MYSQLND_PACKET_CHG_USER_RESPONSE *) _packet;
    2103             : 
    2104          75 :         if (p->new_auth_protocol) {
    2105           0 :                 mnd_efree(p->new_auth_protocol);
    2106           0 :                 p->new_auth_protocol = NULL;
    2107             :         }
    2108          75 :         p->new_auth_protocol_len = 0;
    2109             : 
    2110          75 :         if (p->new_auth_protocol_data) {
    2111           0 :                 mnd_efree(p->new_auth_protocol_data);
    2112           0 :                 p->new_auth_protocol_data = NULL;
    2113             :         }
    2114          75 :         p->new_auth_protocol_data_len = 0;
    2115             : 
    2116          75 :         if (!stack_allocation) {
    2117          75 :                 mnd_pefree(p, p->header.persistent);
    2118             :         }
    2119          75 : }
    2120             : /* }}} */
    2121             : 
    2122             : 
    2123             : /* {{{ php_mysqlnd_sha256_pk_request_write */
    2124             : static
    2125           0 : size_t php_mysqlnd_sha256_pk_request_write(void * _packet, MYSQLND_CONN_DATA * conn)
    2126             : {
    2127             :         zend_uchar buffer[MYSQLND_HEADER_SIZE + 1];
    2128             :         size_t sent;
    2129             : 
    2130           0 :         DBG_ENTER("php_mysqlnd_sha256_pk_request_write");
    2131             : 
    2132           0 :         int1store(buffer + MYSQLND_HEADER_SIZE, '\1');
    2133           0 :         sent = conn->net->data->m.send_ex(conn->net, buffer, 1, conn->stats, conn->error_info);
    2134             : 
    2135           0 :         DBG_RETURN(sent);
    2136             : }
    2137             : /* }}} */
    2138             : 
    2139             : 
    2140             : /* {{{ php_mysqlnd_sha256_pk_request_free_mem */
    2141             : static
    2142           0 : void php_mysqlnd_sha256_pk_request_free_mem(void * _packet, zend_bool stack_allocation)
    2143             : {
    2144           0 :         if (!stack_allocation) {
    2145           0 :                 MYSQLND_PACKET_SHA256_PK_REQUEST * p = (MYSQLND_PACKET_SHA256_PK_REQUEST *) _packet;
    2146           0 :                 mnd_pefree(p, p->header.persistent);
    2147             :         }
    2148           0 : }
    2149             : /* }}} */
    2150             : 
    2151             : 
    2152             : #define SHA256_PK_REQUEST_RESP_BUFFER_SIZE 2048
    2153             : 
    2154             : /* {{{ php_mysqlnd_sha256_pk_request_response_read */
    2155             : static enum_func_status
    2156           0 : php_mysqlnd_sha256_pk_request_response_read(void * _packet, MYSQLND_CONN_DATA * conn)
    2157             : {
    2158             :         zend_uchar buf[SHA256_PK_REQUEST_RESP_BUFFER_SIZE];
    2159           0 :         zend_uchar *p = buf;
    2160           0 :         zend_uchar *begin = buf;
    2161           0 :         MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE * packet= (MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE *) _packet;
    2162             : 
    2163           0 :         DBG_ENTER("php_mysqlnd_sha256_pk_request_response_read");
    2164             : 
    2165             :         /* leave space for terminating safety \0 */
    2166           0 :         PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "SHA256_PK_REQUEST_RESPONSE", PROT_SHA256_PK_REQUEST_RESPONSE_PACKET);
    2167           0 :         BAIL_IF_NO_MORE_DATA;
    2168             : 
    2169           0 :         p++;
    2170           0 :         BAIL_IF_NO_MORE_DATA;
    2171             : 
    2172           0 :         packet->public_key_len = packet->header.size - (p - buf);
    2173           0 :         packet->public_key = mnd_emalloc(packet->public_key_len + 1);
    2174           0 :         memcpy(packet->public_key, p, packet->public_key_len);
    2175           0 :         packet->public_key[packet->public_key_len] = '\0';
    2176             : 
    2177           0 :         DBG_RETURN(PASS);
    2178             : 
    2179             : premature_end:
    2180           0 :         DBG_ERR_FMT("OK packet %d bytes shorter than expected", p - begin - packet->header.size);
    2181           0 :         php_error_docref(NULL, E_WARNING, "SHA256_PK_REQUEST_RESPONSE packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
    2182           0 :                                          p - begin - packet->header.size);
    2183           0 :         DBG_RETURN(FAIL);
    2184             : }
    2185             : /* }}} */
    2186             : 
    2187             : 
    2188             : /* {{{ php_mysqlnd_sha256_pk_request_response_free_mem */
    2189             : static void
    2190           0 : php_mysqlnd_sha256_pk_request_response_free_mem(void * _packet, zend_bool stack_allocation)
    2191             : {
    2192           0 :         MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE * p = (MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE *) _packet;
    2193           0 :         if (p->public_key) {
    2194           0 :                 mnd_efree(p->public_key);
    2195           0 :                 p->public_key = NULL;
    2196             :         }
    2197           0 :         p->public_key_len = 0;
    2198             : 
    2199           0 :         if (!stack_allocation) {
    2200           0 :                 mnd_pefree(p, p->header.persistent);
    2201             :         }
    2202           0 : }
    2203             : /* }}} */
    2204             : 
    2205             : 
    2206             : /* {{{ packet_methods */
    2207             : static
    2208             : mysqlnd_packet_methods packet_methods[PROT_LAST] =
    2209             : {
    2210             :         {
    2211             :                 sizeof(MYSQLND_PACKET_GREET),
    2212             :                 php_mysqlnd_greet_read,
    2213             :                 NULL, /* write */
    2214             :                 php_mysqlnd_greet_free_mem,
    2215             :         }, /* PROT_GREET_PACKET */
    2216             :         {
    2217             :                 sizeof(MYSQLND_PACKET_AUTH),
    2218             :                 NULL, /* read */
    2219             :                 php_mysqlnd_auth_write,
    2220             :                 php_mysqlnd_auth_free_mem,
    2221             :         }, /* PROT_AUTH_PACKET */
    2222             :         {
    2223             :                 sizeof(MYSQLND_PACKET_AUTH_RESPONSE),
    2224             :                 php_mysqlnd_auth_response_read, /* read */
    2225             :                 NULL, /* write */
    2226             :                 php_mysqlnd_auth_response_free_mem,
    2227             :         }, /* PROT_AUTH_RESP_PACKET */
    2228             :         {
    2229             :                 sizeof(MYSQLND_PACKET_CHANGE_AUTH_RESPONSE),
    2230             :                 NULL, /* read */
    2231             :                 php_mysqlnd_change_auth_response_write, /* write */
    2232             :                 php_mysqlnd_change_auth_response_free_mem,
    2233             :         }, /* PROT_CHANGE_AUTH_RESP_PACKET */
    2234             :         {
    2235             :                 sizeof(MYSQLND_PACKET_OK),
    2236             :                 php_mysqlnd_ok_read, /* read */
    2237             :                 NULL, /* write */
    2238             :                 php_mysqlnd_ok_free_mem,
    2239             :         }, /* PROT_OK_PACKET */
    2240             :         {
    2241             :                 sizeof(MYSQLND_PACKET_EOF),
    2242             :                 php_mysqlnd_eof_read, /* read */
    2243             :                 NULL, /* write */
    2244             :                 php_mysqlnd_eof_free_mem,
    2245             :         }, /* PROT_EOF_PACKET */
    2246             :         {
    2247             :                 sizeof(MYSQLND_PACKET_COMMAND),
    2248             :                 NULL, /* read */
    2249             :                 php_mysqlnd_cmd_write, /* write */
    2250             :                 php_mysqlnd_cmd_free_mem,
    2251             :         }, /* PROT_CMD_PACKET */
    2252             :         {
    2253             :                 sizeof(MYSQLND_PACKET_RSET_HEADER),
    2254             :                 php_mysqlnd_rset_header_read, /* read */
    2255             :                 NULL, /* write */
    2256             :                 php_mysqlnd_rset_header_free_mem,
    2257             :         }, /* PROT_RSET_HEADER_PACKET */
    2258             :         {
    2259             :                 sizeof(MYSQLND_PACKET_RES_FIELD),
    2260             :                 php_mysqlnd_rset_field_read, /* read */
    2261             :                 NULL, /* write */
    2262             :                 php_mysqlnd_rset_field_free_mem,
    2263             :         }, /* PROT_RSET_FLD_PACKET */
    2264             :         {
    2265             :                 sizeof(MYSQLND_PACKET_ROW),
    2266             :                 php_mysqlnd_rowp_read, /* read */
    2267             :                 NULL, /* write */
    2268             :                 php_mysqlnd_rowp_free_mem,
    2269             :         }, /* PROT_ROW_PACKET */
    2270             :         {
    2271             :                 sizeof(MYSQLND_PACKET_STATS),
    2272             :                 php_mysqlnd_stats_read, /* read */
    2273             :                 NULL, /* write */
    2274             :                 php_mysqlnd_stats_free_mem,
    2275             :         }, /* PROT_STATS_PACKET */
    2276             :         {
    2277             :                 sizeof(MYSQLND_PACKET_PREPARE_RESPONSE),
    2278             :                 php_mysqlnd_prepare_read, /* read */
    2279             :                 NULL, /* write */
    2280             :                 php_mysqlnd_prepare_free_mem,
    2281             :         }, /* PROT_PREPARE_RESP_PACKET */
    2282             :         {
    2283             :                 sizeof(MYSQLND_PACKET_CHG_USER_RESPONSE),
    2284             :                 php_mysqlnd_chg_user_read, /* read */
    2285             :                 NULL, /* write */
    2286             :                 php_mysqlnd_chg_user_free_mem,
    2287             :         }, /* PROT_CHG_USER_RESP_PACKET */
    2288             :         {
    2289             :                 sizeof(MYSQLND_PACKET_SHA256_PK_REQUEST),
    2290             :                 NULL, /* read */
    2291             :                 php_mysqlnd_sha256_pk_request_write,
    2292             :                 php_mysqlnd_sha256_pk_request_free_mem,
    2293             :         }, /* PROT_SHA256_PK_REQUEST_PACKET */
    2294             :         {
    2295             :                 sizeof(MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE),
    2296             :                 php_mysqlnd_sha256_pk_request_response_read,
    2297             :                 NULL, /* write */
    2298             :                 php_mysqlnd_sha256_pk_request_response_free_mem,
    2299             :         } /* PROT_SHA256_PK_REQUEST_RESPONSE_PACKET */
    2300             : };
    2301             : /* }}} */
    2302             : 
    2303             : 
    2304             : /* {{{ mysqlnd_protocol::get_greet_packet */
    2305             : static struct st_mysqlnd_packet_greet *
    2306        1688 : MYSQLND_METHOD(mysqlnd_protocol, get_greet_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2307             : {
    2308        1688 :         struct st_mysqlnd_packet_greet * packet = mnd_pecalloc(1, packet_methods[PROT_GREET_PACKET].struct_size, persistent);
    2309        1688 :         DBG_ENTER("mysqlnd_protocol::get_greet_packet");
    2310        1688 :         if (packet) {
    2311        1688 :                 packet->header.m = &packet_methods[PROT_GREET_PACKET];
    2312        1688 :                 packet->header.persistent = persistent;
    2313             :         }
    2314        1688 :         DBG_RETURN(packet);
    2315             : }
    2316             : /* }}} */
    2317             : 
    2318             : 
    2319             : /* {{{ mysqlnd_protocol::get_auth_packet */
    2320             : static struct st_mysqlnd_packet_auth *
    2321        3424 : MYSQLND_METHOD(mysqlnd_protocol, get_auth_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2322             : {
    2323        3424 :         struct st_mysqlnd_packet_auth * packet = mnd_pecalloc(1, packet_methods[PROT_AUTH_PACKET].struct_size, persistent);
    2324        3424 :         DBG_ENTER("mysqlnd_protocol::get_auth_packet");
    2325        3424 :         if (packet) {
    2326        3424 :                 packet->header.m = &packet_methods[PROT_AUTH_PACKET];
    2327        3424 :                 packet->header.persistent = persistent;
    2328             :         }
    2329        3424 :         DBG_RETURN(packet);
    2330             : }
    2331             : /* }}} */
    2332             : 
    2333             : 
    2334             : /* {{{ mysqlnd_protocol::get_auth_response_packet */
    2335             : static struct st_mysqlnd_packet_auth_response *
    2336        1673 : MYSQLND_METHOD(mysqlnd_protocol, get_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2337             : {
    2338        1673 :         struct st_mysqlnd_packet_auth_response * packet = mnd_pecalloc(1, packet_methods[PROT_AUTH_RESP_PACKET].struct_size, persistent);
    2339        1673 :         DBG_ENTER("mysqlnd_protocol::get_auth_response_packet");
    2340        1673 :         if (packet) {
    2341        1673 :                 packet->header.m = &packet_methods[PROT_AUTH_RESP_PACKET];
    2342        1673 :                 packet->header.persistent = persistent;
    2343             :         }
    2344        1673 :         DBG_RETURN(packet);
    2345             : }
    2346             : /* }}} */
    2347             : 
    2348             : 
    2349             : /* {{{ mysqlnd_protocol::get_change_auth_response_packet */
    2350             : static struct st_mysqlnd_packet_change_auth_response *
    2351           0 : MYSQLND_METHOD(mysqlnd_protocol, get_change_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2352             : {
    2353           0 :         struct st_mysqlnd_packet_change_auth_response * packet = mnd_pecalloc(1, packet_methods[PROT_CHANGE_AUTH_RESP_PACKET].struct_size, persistent);
    2354           0 :         DBG_ENTER("mysqlnd_protocol::get_change_auth_response_packet");
    2355           0 :         if (packet) {
    2356           0 :                 packet->header.m = &packet_methods[PROT_CHANGE_AUTH_RESP_PACKET];
    2357           0 :                 packet->header.persistent = persistent;
    2358             :         }
    2359           0 :         DBG_RETURN(packet);
    2360             : }
    2361             : /* }}} */
    2362             : 
    2363             : 
    2364             : /* {{{ mysqlnd_protocol::get_ok_packet */
    2365             : static struct st_mysqlnd_packet_ok *
    2366          94 : MYSQLND_METHOD(mysqlnd_protocol, get_ok_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2367             : {
    2368          94 :         struct st_mysqlnd_packet_ok * packet = mnd_pecalloc(1, packet_methods[PROT_OK_PACKET].struct_size, persistent);
    2369          94 :         DBG_ENTER("mysqlnd_protocol::get_ok_packet");
    2370          94 :         if (packet) {
    2371          94 :                 packet->header.m = &packet_methods[PROT_OK_PACKET];
    2372          94 :                 packet->header.persistent = persistent;
    2373             :         }
    2374          94 :         DBG_RETURN(packet);
    2375             : }
    2376             : /* }}} */
    2377             : 
    2378             : 
    2379             : /* {{{ mysqlnd_protocol::get_eof_packet */
    2380             : static struct st_mysqlnd_packet_eof *
    2381        7737 : MYSQLND_METHOD(mysqlnd_protocol, get_eof_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2382             : {
    2383        7737 :         struct st_mysqlnd_packet_eof * packet = mnd_pecalloc(1, packet_methods[PROT_EOF_PACKET].struct_size, persistent);
    2384        7737 :         DBG_ENTER("mysqlnd_protocol::get_eof_packet");
    2385        7737 :         if (packet) {
    2386        7737 :                 packet->header.m = &packet_methods[PROT_EOF_PACKET];
    2387        7737 :                 packet->header.persistent = persistent;
    2388             :         }
    2389        7737 :         DBG_RETURN(packet);
    2390             : }
    2391             : /* }}} */
    2392             : 
    2393             : 
    2394             : /* {{{ mysqlnd_protocol::get_command_packet */
    2395             : static struct st_mysqlnd_packet_command *
    2396       38299 : MYSQLND_METHOD(mysqlnd_protocol, get_command_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2397             : {
    2398       38299 :         struct st_mysqlnd_packet_command * packet = mnd_pecalloc(1, packet_methods[PROT_CMD_PACKET].struct_size, persistent);
    2399       38299 :         DBG_ENTER("mysqlnd_protocol::get_command_packet");
    2400       38299 :         if (packet) {
    2401       38299 :                 packet->header.m = &packet_methods[PROT_CMD_PACKET];
    2402       38299 :                 packet->header.persistent = persistent;
    2403             :         }
    2404       38299 :         DBG_RETURN(packet);
    2405             : }
    2406             : /* }}} */
    2407             : 
    2408             : 
    2409             : /* {{{ mysqlnd_protocol::get_rset_packet */
    2410             : static struct st_mysqlnd_packet_rset_header *
    2411       28058 : MYSQLND_METHOD(mysqlnd_protocol, get_rset_header_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2412             : {
    2413       28058 :         struct st_mysqlnd_packet_rset_header * packet = mnd_pecalloc(1, packet_methods[PROT_RSET_HEADER_PACKET].struct_size, persistent);
    2414       28058 :         DBG_ENTER("mysqlnd_protocol::get_rset_header_packet");
    2415       28058 :         if (packet) {
    2416       28058 :                 packet->header.m = &packet_methods[PROT_RSET_HEADER_PACKET];
    2417       28058 :                 packet->header.persistent = persistent;
    2418             :         }
    2419       28058 :         DBG_RETURN(packet);
    2420             : }
    2421             : /* }}} */
    2422             : 
    2423             : 
    2424             : /* {{{ mysqlnd_protocol::get_result_field_packet */
    2425             : static struct st_mysqlnd_packet_res_field *
    2426        7703 : MYSQLND_METHOD(mysqlnd_protocol, get_result_field_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2427             : {
    2428        7703 :         struct st_mysqlnd_packet_res_field * packet = mnd_pecalloc(1, packet_methods[PROT_RSET_FLD_PACKET].struct_size, persistent);
    2429        7703 :         DBG_ENTER("mysqlnd_protocol::get_result_field_packet");
    2430        7703 :         if (packet) {
    2431        7703 :                 packet->header.m = &packet_methods[PROT_RSET_FLD_PACKET];
    2432        7703 :                 packet->header.persistent = persistent;
    2433             :         }
    2434        7703 :         DBG_RETURN(packet);
    2435             : }
    2436             : /* }}} */
    2437             : 
    2438             : 
    2439             : /* {{{ mysqlnd_protocol::get_row_packet */
    2440             : static struct st_mysqlnd_packet_row *
    2441        4442 : MYSQLND_METHOD(mysqlnd_protocol, get_row_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2442             : {
    2443        4442 :         struct st_mysqlnd_packet_row * packet = mnd_pecalloc(1, packet_methods[PROT_ROW_PACKET].struct_size, persistent);
    2444        4442 :         DBG_ENTER("mysqlnd_protocol::get_row_packet");
    2445        4442 :         if (packet) {
    2446        4442 :                 packet->header.m = &packet_methods[PROT_ROW_PACKET];
    2447        4442 :                 packet->header.persistent = persistent;
    2448             :         }
    2449        4442 :         DBG_RETURN(packet);
    2450             : }
    2451             : /* }}} */
    2452             : 
    2453             : 
    2454             : /* {{{ mysqlnd_protocol::get_stats_packet */
    2455             : static struct st_mysqlnd_packet_stats *
    2456          15 : MYSQLND_METHOD(mysqlnd_protocol, get_stats_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2457             : {
    2458          15 :         struct st_mysqlnd_packet_stats * packet = mnd_pecalloc(1, packet_methods[PROT_STATS_PACKET].struct_size, persistent);
    2459          15 :         DBG_ENTER("mysqlnd_protocol::get_stats_packet");
    2460          15 :         if (packet) {
    2461          15 :                 packet->header.m = &packet_methods[PROT_STATS_PACKET];
    2462          15 :                 packet->header.persistent = persistent;
    2463             :         }
    2464          15 :         DBG_RETURN(packet);
    2465             : }
    2466             : /* }}} */
    2467             : 
    2468             : 
    2469             : /* {{{ mysqlnd_protocol::get_prepare_response_packet */
    2470             : static struct st_mysqlnd_packet_prepare_response *
    2471        4248 : MYSQLND_METHOD(mysqlnd_protocol, get_prepare_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2472             : {
    2473        4248 :         struct st_mysqlnd_packet_prepare_response * packet = mnd_pecalloc(1, packet_methods[PROT_PREPARE_RESP_PACKET].struct_size, persistent);
    2474        4248 :         DBG_ENTER("mysqlnd_protocol::get_prepare_response_packet");
    2475        4248 :         if (packet) {
    2476        4248 :                 packet->header.m = &packet_methods[PROT_PREPARE_RESP_PACKET];
    2477        4248 :                 packet->header.persistent = persistent;
    2478             :         }
    2479        4248 :         DBG_RETURN(packet);
    2480             : }
    2481             : /* }}} */
    2482             : 
    2483             : 
    2484             : /* {{{ mysqlnd_protocol::get_change_user_response_packet */
    2485             : static struct st_mysqlnd_packet_chg_user_resp*
    2486          75 : MYSQLND_METHOD(mysqlnd_protocol, get_change_user_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2487             : {
    2488          75 :         struct st_mysqlnd_packet_chg_user_resp * packet = mnd_pecalloc(1, packet_methods[PROT_CHG_USER_RESP_PACKET].struct_size, persistent);
    2489          75 :         DBG_ENTER("mysqlnd_protocol::get_change_user_response_packet");
    2490          75 :         if (packet) {
    2491          75 :                 packet->header.m = &packet_methods[PROT_CHG_USER_RESP_PACKET];
    2492          75 :                 packet->header.persistent = persistent;
    2493             :         }
    2494          75 :         DBG_RETURN(packet);
    2495             : }
    2496             : /* }}} */
    2497             : 
    2498             : 
    2499             : /* {{{ mysqlnd_protocol::get_sha256_pk_request_packet */
    2500             : static struct st_mysqlnd_packet_sha256_pk_request *
    2501           0 : MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2502             : {
    2503           0 :         struct st_mysqlnd_packet_sha256_pk_request * packet = mnd_pecalloc(1, packet_methods[PROT_SHA256_PK_REQUEST_PACKET].struct_size, persistent);
    2504           0 :         DBG_ENTER("mysqlnd_protocol::get_sha256_pk_request_packet");
    2505           0 :         if (packet) {
    2506           0 :                 packet->header.m = &packet_methods[PROT_SHA256_PK_REQUEST_PACKET];
    2507           0 :                 packet->header.persistent = persistent;
    2508             :         }
    2509           0 :         DBG_RETURN(packet);
    2510             : }
    2511             : /* }}} */
    2512             : 
    2513             : 
    2514             : /* {{{ mysqlnd_protocol::get_sha256_pk_request_response_packet */
    2515             : static struct st_mysqlnd_packet_sha256_pk_request_response *
    2516           0 : MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
    2517             : {
    2518           0 :         struct st_mysqlnd_packet_sha256_pk_request_response * packet = mnd_pecalloc(1, packet_methods[PROT_SHA256_PK_REQUEST_RESPONSE_PACKET].struct_size, persistent);
    2519           0 :         DBG_ENTER("mysqlnd_protocol::get_sha256_pk_request_response_packet");
    2520           0 :         if (packet) {
    2521           0 :                 packet->header.m = &packet_methods[PROT_SHA256_PK_REQUEST_RESPONSE_PACKET];
    2522           0 :                 packet->header.persistent = persistent;
    2523             :         }
    2524           0 :         DBG_RETURN(packet);
    2525             : }
    2526             : /* }}} */
    2527             : 
    2528             : 
    2529             : 
    2530             : MYSQLND_CLASS_METHODS_START(mysqlnd_protocol)
    2531             :         MYSQLND_METHOD(mysqlnd_protocol, get_greet_packet),
    2532             :         MYSQLND_METHOD(mysqlnd_protocol, get_auth_packet),
    2533             :         MYSQLND_METHOD(mysqlnd_protocol, get_auth_response_packet),
    2534             :         MYSQLND_METHOD(mysqlnd_protocol, get_change_auth_response_packet),
    2535             :         MYSQLND_METHOD(mysqlnd_protocol, get_ok_packet),
    2536             :         MYSQLND_METHOD(mysqlnd_protocol, get_command_packet),
    2537             :         MYSQLND_METHOD(mysqlnd_protocol, get_eof_packet),
    2538             :         MYSQLND_METHOD(mysqlnd_protocol, get_rset_header_packet),
    2539             :         MYSQLND_METHOD(mysqlnd_protocol, get_result_field_packet),
    2540             :         MYSQLND_METHOD(mysqlnd_protocol, get_row_packet),
    2541             :         MYSQLND_METHOD(mysqlnd_protocol, get_stats_packet),
    2542             :         MYSQLND_METHOD(mysqlnd_protocol, get_prepare_response_packet),
    2543             :         MYSQLND_METHOD(mysqlnd_protocol, get_change_user_response_packet),
    2544             :         MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_packet),
    2545             :         MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_response_packet)
    2546             : MYSQLND_CLASS_METHODS_END;
    2547             : 
    2548             : 
    2549             : /* {{{ mysqlnd_protocol_init */
    2550             : PHPAPI MYSQLND_PROTOCOL *
    2551        1755 : mysqlnd_protocol_init(zend_bool persistent)
    2552             : {
    2553             :         MYSQLND_PROTOCOL * ret;
    2554        1755 :         DBG_ENTER("mysqlnd_protocol_init");
    2555        1755 :         ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_protocol_decoder(persistent);
    2556        1755 :         DBG_RETURN(ret);
    2557             : }
    2558             : /* }}} */
    2559             : 
    2560             : 
    2561             : /* {{{ mysqlnd_protocol_free */
    2562             : PHPAPI void
    2563        1714 : mysqlnd_protocol_free(MYSQLND_PROTOCOL * const protocol)
    2564             : {
    2565        1714 :         DBG_ENTER("mysqlnd_protocol_free");
    2566             : 
    2567        1714 :         if (protocol) {
    2568        1714 :                 zend_bool pers = protocol->persistent;
    2569        1714 :                 mnd_pefree(protocol, pers);
    2570             :         }
    2571        1714 :         DBG_VOID_RETURN;
    2572             : }
    2573             : /* }}} */
    2574             : 
    2575             : 
    2576             : /*
    2577             :  * Local variables:
    2578             :  * tab-width: 4
    2579             :  * c-basic-offset: 4
    2580             :  * End:
    2581             :  * vim600: noet sw=4 ts=4 fdm=marker
    2582             :  * vim<600: noet sw=4 ts=4
    2583             :  */

Generated by: LCOV version 1.10

Generated at Wed, 02 Sep 2015 17:19:13 +0000 (2 days ago)

Copyright © 2005-2015 The PHP Group
All rights reserved.