trilogy 2.9.0 → 2.12.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,13 @@
1
1
  #include <fcntl.h>
2
-
2
+ #include <limits.h>
3
+ #include <openssl/err.h>
4
+ #include <openssl/evp.h>
5
+ #include <openssl/pem.h>
6
+ #include <openssl/rsa.h>
7
+ #include <stdlib.h>
8
+ #include <string.h>
9
+
10
+ #include "trilogy/allocator.h"
3
11
  #include "trilogy/client.h"
4
12
  #include "trilogy/error.h"
5
13
 
@@ -117,10 +125,40 @@ static int begin_write(trilogy_conn_t *conn)
117
125
  return trilogy_flush_writes(conn);
118
126
  }
119
127
 
120
- int trilogy_init(trilogy_conn_t *conn)
128
+ static int flush_current_packet(trilogy_conn_t *conn)
129
+ {
130
+ int rc = begin_write(conn);
131
+
132
+ while (rc == TRILOGY_AGAIN) {
133
+ rc = trilogy_sock_wait_write(conn->socket);
134
+
135
+ if (rc != TRILOGY_OK) {
136
+ return rc;
137
+ }
138
+
139
+ rc = trilogy_flush_writes(conn);
140
+ }
141
+
142
+ return rc;
143
+ }
144
+
145
+ static int read_packet_blocking(trilogy_conn_t *conn)
121
146
  {
122
147
  int rc;
123
148
 
149
+ while ((rc = read_packet(conn)) == TRILOGY_AGAIN) {
150
+ rc = trilogy_sock_wait_read(conn->socket);
151
+
152
+ if (rc != TRILOGY_OK) {
153
+ return rc;
154
+ }
155
+ }
156
+
157
+ return rc;
158
+ }
159
+
160
+ int trilogy_init_no_buffer(trilogy_conn_t *conn)
161
+ {
124
162
  conn->affected_rows = 0;
125
163
  conn->last_insert_id = 0;
126
164
  conn->warning_count = 0;
@@ -142,8 +180,14 @@ int trilogy_init(trilogy_conn_t *conn)
142
180
  trilogy_packet_parser_init(&conn->packet_parser, &packet_parser_callbacks);
143
181
  conn->packet_parser.user_data = &conn->packet_buffer;
144
182
 
145
- CHECKED(trilogy_buffer_init(&conn->packet_buffer, TRILOGY_DEFAULT_BUF_SIZE));
183
+ return TRILOGY_OK;
184
+ }
146
185
 
186
+ int trilogy_init(trilogy_conn_t *conn)
187
+ {
188
+ int rc;
189
+ trilogy_init_no_buffer(conn);
190
+ CHECKED(trilogy_buffer_init(&conn->packet_buffer, TRILOGY_DEFAULT_BUF_SIZE));
147
191
  return TRILOGY_OK;
148
192
  }
149
193
 
@@ -217,7 +261,7 @@ static int read_err_packet(trilogy_conn_t *conn)
217
261
  return TRILOGY_ERR;
218
262
  }
219
263
 
220
- static int read_eof_packet(trilogy_conn_t *conn)
264
+ static int read_deprecated_eof_packet(trilogy_conn_t *conn)
221
265
  {
222
266
  trilogy_eof_packet_t eof_packet;
223
267
 
@@ -236,6 +280,36 @@ static int read_eof_packet(trilogy_conn_t *conn)
236
280
  return TRILOGY_EOF;
237
281
  }
238
282
 
283
+ bool is_eof_packet(trilogy_conn_t *conn)
284
+ {
285
+ // An EOF packet first byte can mark an EOF/OK packet, a deprecated EOF packet, or a huge data packet.
286
+ if (current_packet_type(conn) == TRILOGY_PACKET_EOF) {
287
+ if (conn->capabilities & TRILOGY_CAPABILITIES_DEPRECATE_EOF) {
288
+ // The EOF/OK packet can contain an info message and/or session state info up to max packet length.
289
+ return conn->packet_buffer.len <= TRILOGY_MAX_PACKET_LEN;
290
+ } else {
291
+ // The deprecated EOF packet must be smaller than 9 bytes (one 8-byte length-encoded integer).
292
+ return conn->packet_buffer.len < 9;
293
+ }
294
+ }
295
+ return false;
296
+ }
297
+
298
+ static int read_eof_packet(trilogy_conn_t *conn)
299
+ {
300
+ int rc;
301
+
302
+ if (conn->capabilities & TRILOGY_CAPABILITIES_DEPRECATE_EOF) {
303
+ return read_ok_packet(conn);
304
+ } else {
305
+ if ((rc = read_deprecated_eof_packet(conn)) != TRILOGY_EOF) {
306
+ return rc;
307
+ }
308
+
309
+ return TRILOGY_OK;
310
+ }
311
+ }
312
+
239
313
  static int read_auth_switch_packet(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
240
314
  {
241
315
  trilogy_auth_switch_request_packet_t auth_switch_packet;
@@ -259,7 +333,8 @@ static int read_auth_switch_packet(trilogy_conn_t *conn, trilogy_handshake_t *ha
259
333
  return TRILOGY_AUTH_SWITCH;
260
334
  }
261
335
 
262
- static int handle_generic_response(trilogy_conn_t *conn) {
336
+ static int handle_generic_response(trilogy_conn_t *conn)
337
+ {
263
338
  switch (current_packet_type(conn)) {
264
339
  case TRILOGY_PACKET_OK:
265
340
  return read_ok_packet(conn);
@@ -310,6 +385,16 @@ int trilogy_connect_send_socket(trilogy_conn_t *conn, trilogy_sock_t *sock)
310
385
  return TRILOGY_OK;
311
386
  }
312
387
 
388
+ int trilogy_connect_set_fd(trilogy_conn_t *conn, trilogy_sock_t *sock, int fd)
389
+ {
390
+ trilogy_sock_set_fd(sock, fd);
391
+
392
+ conn->socket = sock;
393
+ conn->packet_parser.sequence_number = 0;
394
+
395
+ return TRILOGY_OK;
396
+ }
397
+
313
398
  int trilogy_connect_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake_out)
314
399
  {
315
400
  int rc = read_packet(conn);
@@ -407,9 +492,294 @@ void trilogy_auth_clear_password(trilogy_conn_t *conn)
407
492
  }
408
493
  }
409
494
 
495
+ #define CACHING_SHA2_REQUEST_PUBLIC_KEY 2
496
+ #define CACHING_SHA2_SCRAMBLE_LEN 20
410
497
  #define FAST_AUTH_OK 3
411
498
  #define FAST_AUTH_FAIL 4
412
499
 
500
+ static int read_auth_result(trilogy_conn_t *conn)
501
+ {
502
+ int rc = read_packet_blocking(conn);
503
+
504
+ if (rc < 0) {
505
+ return rc;
506
+ }
507
+
508
+ trilogy_auth_clear_password(conn);
509
+ return handle_generic_response(conn);
510
+ }
511
+
512
+ static int send_cleartext_password(trilogy_conn_t *conn)
513
+ {
514
+ trilogy_builder_t builder;
515
+
516
+ int rc = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
517
+
518
+ if (rc < 0) {
519
+ return rc;
520
+ }
521
+
522
+ if (conn->socket->opts.password_len == 0) {
523
+ rc = trilogy_builder_write_uint8(&builder, 0);
524
+
525
+ if (rc < 0) {
526
+ return rc;
527
+ }
528
+
529
+ trilogy_builder_finalize(&builder);
530
+ return flush_current_packet(conn);
531
+ }
532
+
533
+ rc = trilogy_build_auth_clear_password(&builder, conn->socket->opts.password, conn->socket->opts.password_len);
534
+
535
+ if (rc < 0) {
536
+ return rc;
537
+ }
538
+
539
+ return flush_current_packet(conn);
540
+ }
541
+
542
+ static int send_auth_buffer(trilogy_conn_t *conn, const void *buff, size_t buff_len)
543
+ {
544
+ trilogy_builder_t builder;
545
+ int rc = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
546
+
547
+ if (rc < 0) {
548
+ return rc;
549
+ }
550
+
551
+ rc = trilogy_builder_write_buffer(&builder, buff, buff_len);
552
+ if (rc < 0) {
553
+ return rc;
554
+ }
555
+
556
+ trilogy_builder_finalize(&builder);
557
+
558
+ return flush_current_packet(conn);
559
+ }
560
+
561
+ static int send_public_key_request(trilogy_conn_t *conn)
562
+ {
563
+ uint8_t request = CACHING_SHA2_REQUEST_PUBLIC_KEY;
564
+
565
+ return send_auth_buffer(conn, &request, sizeof(request));
566
+ }
567
+
568
+ static int encrypt_password_with_public_key(const uint8_t *scramble, size_t scramble_len, trilogy_conn_t *conn,
569
+ const uint8_t *key_data, size_t key_data_len, uint8_t **encrypted_out,
570
+ size_t *encrypted_len)
571
+ {
572
+ int rc = TRILOGY_OK;
573
+ uint8_t *ciphertext = NULL;
574
+ size_t ciphertext_len = 0;
575
+
576
+ if (key_data_len == 0 || key_data_len > INT_MAX) {
577
+ return TRILOGY_AUTH_PLUGIN_ERROR;
578
+ }
579
+
580
+ size_t password_len = conn->socket->opts.password_len;
581
+ if (password_len == SIZE_MAX) {
582
+ return TRILOGY_MEM_ERROR;
583
+ }
584
+ size_t plaintext_len = password_len + 1;
585
+ uint8_t *plaintext = xmalloc(plaintext_len);
586
+
587
+ if (plaintext == NULL) {
588
+ return TRILOGY_MEM_ERROR;
589
+ }
590
+
591
+ if (password_len > 0) {
592
+ memcpy(plaintext, conn->socket->opts.password, password_len);
593
+ }
594
+ plaintext[plaintext_len - 1] = '\0';
595
+
596
+ if (scramble_len > 0) {
597
+ for (size_t i = 0; i < plaintext_len; i++) {
598
+ plaintext[i] ^= scramble[i % scramble_len];
599
+ }
600
+ }
601
+
602
+ BIO *bio = BIO_new_mem_buf((void *)key_data, (int)key_data_len);
603
+ if (bio == NULL) {
604
+ xfree(plaintext);
605
+ return TRILOGY_OPENSSL_ERR;
606
+ }
607
+
608
+ #if OPENSSL_VERSION_NUMBER >= 0x30000000L
609
+ EVP_PKEY *public_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
610
+ #else
611
+ RSA *public_key = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
612
+ #endif
613
+
614
+ BIO_free(bio);
615
+
616
+ if (public_key == NULL) {
617
+ ERR_clear_error();
618
+ memset(plaintext, 0, plaintext_len);
619
+ xfree(plaintext);
620
+ return TRILOGY_AUTH_PLUGIN_ERROR;
621
+ }
622
+
623
+ #if OPENSSL_VERSION_NUMBER >= 0x30000000L
624
+ int key_size = EVP_PKEY_get_size(public_key);
625
+ if (key_size <= 0) {
626
+ EVP_PKEY_free(public_key);
627
+ memset(plaintext, 0, plaintext_len);
628
+ xfree(plaintext);
629
+ return TRILOGY_AUTH_PLUGIN_ERROR;
630
+ }
631
+ ciphertext_len = (size_t)key_size;
632
+ #else
633
+ ciphertext_len = (size_t)RSA_size(public_key);
634
+ #endif
635
+
636
+ /*
637
+ When using RSA_PKCS1_OAEP_PADDING the password length must be less
638
+ than RSA_size(rsa) - 41.
639
+ */
640
+ if (ciphertext_len == 0 || plaintext_len + 41 >= ciphertext_len) {
641
+ #if OPENSSL_VERSION_NUMBER >= 0x30000000L
642
+ EVP_PKEY_free(public_key);
643
+ #else
644
+ RSA_free(public_key);
645
+ #endif
646
+ memset(plaintext, 0, plaintext_len);
647
+ xfree(plaintext);
648
+ return TRILOGY_AUTH_PLUGIN_ERROR;
649
+ }
650
+
651
+ ciphertext = xmalloc(ciphertext_len);
652
+
653
+ if (ciphertext == NULL) {
654
+ #if OPENSSL_VERSION_NUMBER >= 0x30000000L
655
+ EVP_PKEY_free(public_key);
656
+ #else
657
+ RSA_free(public_key);
658
+ #endif
659
+ memset(plaintext, 0, plaintext_len);
660
+ xfree(plaintext);
661
+ return TRILOGY_MEM_ERROR;
662
+ }
663
+
664
+ #if OPENSSL_VERSION_NUMBER >= 0x30000000L
665
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(public_key, NULL);
666
+ if (ctx == NULL || EVP_PKEY_encrypt_init(ctx) <= 0 ||
667
+ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
668
+ rc = TRILOGY_OPENSSL_ERR;
669
+ } else {
670
+ size_t out_len = ciphertext_len;
671
+
672
+ if (EVP_PKEY_encrypt(ctx, ciphertext, &out_len, plaintext, plaintext_len) <= 0) {
673
+ rc = TRILOGY_OPENSSL_ERR;
674
+ } else {
675
+ *encrypted_len = out_len;
676
+ }
677
+ }
678
+
679
+ if (ctx) {
680
+ EVP_PKEY_CTX_free(ctx);
681
+ }
682
+ EVP_PKEY_free(public_key);
683
+ #else
684
+ int out_len = RSA_public_encrypt((int)plaintext_len, plaintext, ciphertext, public_key, RSA_PKCS1_OAEP_PADDING);
685
+ RSA_free(public_key);
686
+
687
+ if (out_len < 0) {
688
+ rc = TRILOGY_OPENSSL_ERR;
689
+ } else {
690
+ *encrypted_len = (size_t)out_len;
691
+ }
692
+ #endif
693
+
694
+ memset(plaintext, 0, plaintext_len);
695
+ xfree(plaintext);
696
+
697
+ if (rc == TRILOGY_OK) {
698
+ *encrypted_out = ciphertext;
699
+ } else {
700
+ memset(ciphertext, 0, ciphertext_len);
701
+ xfree(ciphertext);
702
+ }
703
+
704
+ return rc;
705
+ }
706
+
707
+ static int handle_fast_auth_fail(trilogy_conn_t *conn, trilogy_handshake_t *handshake, const uint8_t *auth_data,
708
+ size_t auth_data_len)
709
+ {
710
+ int rc;
711
+ bool use_ssl = (conn->socket->opts.flags & TRILOGY_CAPABILITIES_SSL) != 0;
712
+ bool has_unix_socket = (conn->socket->opts.path != NULL);
713
+
714
+ // No password to send, so we can safely respond even without TLS.
715
+ if (conn->socket->opts.password_len == 0) {
716
+ rc = send_cleartext_password(conn);
717
+ if (rc < 0) {
718
+ return rc;
719
+ }
720
+
721
+ return read_auth_result(conn);
722
+ }
723
+
724
+ if (use_ssl || has_unix_socket) {
725
+ rc = send_cleartext_password(conn);
726
+ if (rc < 0) {
727
+ return rc;
728
+ }
729
+
730
+ return read_auth_result(conn);
731
+ }
732
+
733
+ const uint8_t *public_key_data = NULL;
734
+ size_t public_key_len = 0;
735
+
736
+ if (auth_data_len > 1) {
737
+ public_key_data = auth_data + 1;
738
+ public_key_len = auth_data_len - 1;
739
+ } else {
740
+ rc = send_public_key_request(conn);
741
+ if (rc < 0) {
742
+ return rc;
743
+ }
744
+
745
+ rc = read_packet_blocking(conn);
746
+ if (rc < 0) {
747
+ return rc;
748
+ }
749
+
750
+ if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
751
+ return read_err_packet(conn);
752
+ }
753
+
754
+ if (current_packet_type(conn) != TRILOGY_PACKET_AUTH_MORE_DATA || conn->packet_buffer.len < 2) {
755
+ return TRILOGY_PROTOCOL_VIOLATION;
756
+ }
757
+
758
+ public_key_data = conn->packet_buffer.buff + 1;
759
+ public_key_len = conn->packet_buffer.len - 1;
760
+ }
761
+
762
+ uint8_t *encrypted = NULL;
763
+ size_t encrypted_len = 0;
764
+
765
+ rc = encrypt_password_with_public_key((const uint8_t *)handshake->scramble, CACHING_SHA2_SCRAMBLE_LEN, conn,
766
+ public_key_data, public_key_len, &encrypted, &encrypted_len);
767
+
768
+ if (rc < 0) {
769
+ return rc;
770
+ }
771
+
772
+ rc = send_auth_buffer(conn, encrypted, encrypted_len);
773
+ memset(encrypted, 0, encrypted_len);
774
+ xfree(encrypted);
775
+
776
+ if (rc < 0) {
777
+ return rc;
778
+ }
779
+
780
+ return read_auth_result(conn);
781
+ }
782
+
413
783
  int trilogy_auth_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
414
784
  {
415
785
  int rc = read_packet(conn);
@@ -420,67 +790,24 @@ int trilogy_auth_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
420
790
 
421
791
  switch (current_packet_type(conn)) {
422
792
  case TRILOGY_PACKET_AUTH_MORE_DATA: {
423
- bool use_ssl = (conn->socket->opts.flags & TRILOGY_CAPABILITIES_SSL) != 0;
424
- bool has_unix_socket = (conn->socket->opts.path != NULL);
793
+ const uint8_t *auth_data = conn->packet_buffer.buff + 1;
794
+ size_t auth_data_len = conn->packet_buffer.len - 1;
425
795
 
426
- if (!use_ssl && !has_unix_socket) {
427
- return TRILOGY_UNSUPPORTED;
796
+ if (auth_data_len < 1) {
797
+ return TRILOGY_PROTOCOL_VIOLATION;
428
798
  }
429
799
 
430
- uint8_t byte = conn->packet_buffer.buff[1];
800
+ uint8_t byte = auth_data[0];
431
801
  switch (byte) {
432
- case FAST_AUTH_OK:
433
- break;
434
- case FAST_AUTH_FAIL:
435
- {
436
- trilogy_builder_t builder;
437
- int err = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
438
-
439
- if (err < 0) {
440
- return err;
441
- }
442
-
443
- err = trilogy_build_auth_clear_password(&builder, conn->socket->opts.password, conn->socket->opts.password_len);
444
-
445
- if (err < 0) {
446
- return err;
447
- }
448
-
449
- int rc = begin_write(conn);
450
-
451
- while (rc == TRILOGY_AGAIN) {
452
- rc = trilogy_sock_wait_write(conn->socket);
453
- if (rc != TRILOGY_OK) {
454
- return rc;
455
- }
456
-
457
- rc = trilogy_flush_writes(conn);
458
- }
459
- if (rc != TRILOGY_OK) {
460
- return rc;
461
- }
462
-
463
- break;
464
- }
465
- default:
466
- return TRILOGY_UNEXPECTED_PACKET;
467
- }
468
- while (1) {
469
- rc = read_packet(conn);
802
+ case FAST_AUTH_OK:
803
+ return read_auth_result(conn);
470
804
 
471
- if (rc == TRILOGY_OK) {
472
- break;
473
- }
474
- else if (rc == TRILOGY_AGAIN) {
475
- rc = trilogy_sock_wait_read(conn->socket);
476
- }
805
+ case FAST_AUTH_FAIL:
806
+ return handle_fast_auth_fail(conn, handshake, auth_data, auth_data_len);
477
807
 
478
- if (rc != TRILOGY_OK) {
479
- return rc;
480
- }
808
+ default:
809
+ return TRILOGY_UNEXPECTED_PACKET;
481
810
  }
482
- trilogy_auth_clear_password(conn);
483
- return handle_generic_response(conn);
484
811
  }
485
812
 
486
813
  case TRILOGY_PACKET_EOF:
@@ -535,7 +862,8 @@ int trilogy_set_option_send(trilogy_conn_t *conn, const uint16_t option)
535
862
  return begin_write(conn);
536
863
  }
537
864
 
538
- int trilogy_set_option_recv(trilogy_conn_t *conn) {
865
+ int trilogy_set_option_recv(trilogy_conn_t *conn)
866
+ {
539
867
  int rc = read_packet(conn);
540
868
 
541
869
  if (rc < 0) {
@@ -555,7 +883,6 @@ int trilogy_set_option_recv(trilogy_conn_t *conn) {
555
883
  }
556
884
  }
557
885
 
558
-
559
886
  int trilogy_ping_send(trilogy_conn_t *conn)
560
887
  {
561
888
  trilogy_builder_t builder;
@@ -646,15 +973,7 @@ static int read_eof(trilogy_conn_t *conn)
646
973
  return rc;
647
974
  }
648
975
 
649
- if (conn->capabilities & TRILOGY_CAPABILITIES_DEPRECATE_EOF) {
650
- return read_ok_packet(conn);
651
- } else {
652
- if ((rc = read_eof_packet(conn)) != TRILOGY_EOF) {
653
- return rc;
654
- }
655
-
656
- return TRILOGY_OK;
657
- }
976
+ return read_eof_packet(conn);
658
977
  }
659
978
 
660
979
  int trilogy_read_row(trilogy_conn_t *conn, trilogy_value_t *values_out)
@@ -679,14 +998,12 @@ int trilogy_read_row(trilogy_conn_t *conn, trilogy_value_t *values_out)
679
998
  return rc;
680
999
  }
681
1000
 
682
- if (conn->capabilities & TRILOGY_CAPABILITIES_DEPRECATE_EOF && current_packet_type(conn) == TRILOGY_PACKET_EOF) {
683
- if ((rc = read_ok_packet(conn)) != TRILOGY_OK) {
1001
+ if (is_eof_packet(conn)) {
1002
+ if ((rc = read_eof_packet(conn)) != TRILOGY_OK) {
684
1003
  return rc;
685
1004
  }
686
1005
 
687
1006
  return TRILOGY_EOF;
688
- } else if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
689
- return read_eof_packet(conn);
690
1007
  } else if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
691
1008
  return read_err_packet(conn);
692
1009
  } else {
@@ -716,13 +1033,14 @@ int trilogy_drain_results(trilogy_conn_t *conn)
716
1033
  return rc;
717
1034
  }
718
1035
 
719
- if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
1036
+ if (is_eof_packet(conn)) {
1037
+ read_eof_packet(conn);
720
1038
  return TRILOGY_OK;
721
1039
  }
722
1040
  }
723
1041
  }
724
1042
 
725
- static uint8_t escape_lookup_table[256] = {
1043
+ static const uint8_t escape_lookup_table[256] = {
726
1044
  ['"'] = '"', ['\0'] = '0', ['\''] = '\'', ['\\'] = '\\', ['\n'] = 'n', ['\r'] = 'r', [26] = 'Z',
727
1045
  };
728
1046
 
@@ -735,28 +1053,40 @@ int trilogy_escape(trilogy_conn_t *conn, const char *str, size_t len, const char
735
1053
 
736
1054
  b->len = 0;
737
1055
 
738
- if (conn->server_status & TRILOGY_SERVER_STATUS_NO_BACKSLASH_ESCAPES) {
739
- for (size_t i = 0; i < len; i++) {
740
- const uint8_t c = (uint8_t)str[i];
1056
+ // Escaped string will be at least as large as the source string,
1057
+ // so might as well pre-expand the buffer.
1058
+ CHECKED(trilogy_buffer_expand(b, len));
741
1059
 
742
- if (c == '\'') {
743
- CHECKED(trilogy_buffer_putc(b, '\''));
744
- CHECKED(trilogy_buffer_putc(b, '\''));
1060
+ const uint8_t *cursor = (const uint8_t *)str;
1061
+ const uint8_t *end = cursor + len;
1062
+
1063
+ if (conn->server_status & TRILOGY_SERVER_STATUS_NO_BACKSLASH_ESCAPES) {
1064
+ while (cursor < end) {
1065
+ uint8_t *next_escape = memchr(cursor, '\'', (size_t)(end - cursor));
1066
+ if (next_escape) {
1067
+ CHECKED(trilogy_buffer_write(b, cursor, (size_t)(next_escape - cursor)));
1068
+ CHECKED(trilogy_buffer_write(b, (uint8_t *)"\'\'", 2));
1069
+ cursor = next_escape + 1;
745
1070
  } else {
746
- CHECKED(trilogy_buffer_putc(b, c));
1071
+ CHECKED(trilogy_buffer_write(b, cursor, (size_t)(end - cursor)));
1072
+ break;
747
1073
  }
748
1074
  }
749
1075
  } else {
750
- for (size_t i = 0; i < len; i++) {
751
- const uint8_t c = (uint8_t)str[i];
752
-
753
- uint8_t escaped = escape_lookup_table[(uint8_t)c];
1076
+ while (cursor < end) {
1077
+ uint8_t escaped = 0;
1078
+ const uint8_t *start = cursor;
1079
+ while (cursor < end && !(escaped = escape_lookup_table[*cursor])) {
1080
+ cursor++;
1081
+ }
754
1082
 
1083
+ CHECKED(trilogy_buffer_write(b, start, (size_t)(cursor - start)));
755
1084
  if (escaped) {
756
1085
  CHECKED(trilogy_buffer_putc(b, '\\'));
757
1086
  CHECKED(trilogy_buffer_putc(b, escaped));
1087
+ cursor++;
758
1088
  } else {
759
- CHECKED(trilogy_buffer_putc(b, c));
1089
+ break;
760
1090
  }
761
1091
  }
762
1092
  }
@@ -940,20 +1270,18 @@ int trilogy_stmt_bind_data_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt, uint
940
1270
  int trilogy_stmt_read_row(trilogy_conn_t *conn, trilogy_stmt_t *stmt, trilogy_column_packet_t *columns,
941
1271
  trilogy_binary_value_t *values_out)
942
1272
  {
943
- int err = read_packet(conn);
1273
+ int rc = read_packet(conn);
944
1274
 
945
- if (err < 0) {
946
- return err;
1275
+ if (rc < 0) {
1276
+ return rc;
947
1277
  }
948
1278
 
949
- if (conn->capabilities & TRILOGY_CAPABILITIES_DEPRECATE_EOF && current_packet_type(conn) == TRILOGY_PACKET_EOF) {
950
- if ((err = read_ok_packet(conn)) != TRILOGY_OK) {
951
- return err;
1279
+ if (is_eof_packet(conn)) {
1280
+ if ((rc = read_eof_packet(conn)) != TRILOGY_OK) {
1281
+ return rc;
952
1282
  }
953
1283
 
954
1284
  return TRILOGY_EOF;
955
- } else if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
956
- return read_eof_packet(conn);
957
1285
  } else if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
958
1286
  return read_err_packet(conn);
959
1287
  } else {
@@ -978,9 +1306,7 @@ int trilogy_stmt_reset_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt)
978
1306
  return begin_write(conn);
979
1307
  }
980
1308
 
981
- int trilogy_stmt_reset_recv(trilogy_conn_t *conn) {
982
- return read_generic_response(conn);
983
- }
1309
+ int trilogy_stmt_reset_recv(trilogy_conn_t *conn) { return read_generic_response(conn); }
984
1310
 
985
1311
  int trilogy_stmt_close_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt)
986
1312
  {
@@ -74,7 +74,7 @@ size_t trilogy_packet_parser_execute(trilogy_packet_parser_t *parser, const uint
74
74
  break;
75
75
  }
76
76
  case S_SEQ: {
77
- if (cur_byte != parser->sequence_number) {
77
+ if (cur_byte != parser->sequence_number && cur_byte > 0) {
78
78
  *error = TRILOGY_INVALID_SEQUENCE_ID;
79
79
  return i;
80
80
  }