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