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

Generated by: LCOV version 1.10

Generated at Sat, 27 Sep 2014 16:43:12 +0000 (4 days ago)

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