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: 890 1164 76.5 %
Date: 2014-07-21 Functions: 48 58 82.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 22 Jul 2014 01:33:13 +0000 (10 days ago)

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