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