trilogy 2.9.0 → 2.11.0

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,6 @@
1
1
  #include <stdint.h>
2
2
  #include <stdlib.h>
3
+ #include <string.h>
3
4
 
4
5
  #include "trilogy/buffer.h"
5
6
  #include "trilogy/error.h"
@@ -23,6 +24,9 @@ int trilogy_buffer_expand(trilogy_buffer_t *buffer, size_t needed)
23
24
  {
24
25
  // expand buffer if necessary
25
26
  if (buffer->len + needed > buffer->cap) {
27
+ if (buffer->buff == NULL)
28
+ return TRILOGY_MEM_ERROR;
29
+
26
30
  size_t new_cap = buffer->cap;
27
31
 
28
32
  while (buffer->len + needed > new_cap) {
@@ -57,9 +61,24 @@ int trilogy_buffer_putc(trilogy_buffer_t *buffer, uint8_t c)
57
61
  return TRILOGY_OK;
58
62
  }
59
63
 
64
+ int trilogy_buffer_write(trilogy_buffer_t *buffer, const uint8_t *ptr, size_t len)
65
+ {
66
+ int rc = trilogy_buffer_expand(buffer, len);
67
+ if (rc) {
68
+ return rc;
69
+ }
70
+
71
+ memcpy(buffer->buff + buffer->len, ptr, len);
72
+ buffer->len += len;
73
+
74
+ return TRILOGY_OK;
75
+ }
76
+
60
77
  void trilogy_buffer_free(trilogy_buffer_t *buffer)
61
78
  {
62
- free(buffer->buff);
63
- buffer->buff = NULL;
64
- buffer->len = buffer->cap = 0;
79
+ if (buffer->buff) {
80
+ free(buffer->buff);
81
+ buffer->buff = NULL;
82
+ buffer->len = buffer->cap = 0;
83
+ }
65
84
  }
@@ -1,4 +1,11 @@
1
1
  #include <fcntl.h>
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>
2
9
 
3
10
  #include "trilogy/client.h"
4
11
  #include "trilogy/error.h"
@@ -117,10 +124,40 @@ static int begin_write(trilogy_conn_t *conn)
117
124
  return trilogy_flush_writes(conn);
118
125
  }
119
126
 
120
- int trilogy_init(trilogy_conn_t *conn)
127
+ static int flush_current_packet(trilogy_conn_t *conn)
128
+ {
129
+ int rc = begin_write(conn);
130
+
131
+ while (rc == TRILOGY_AGAIN) {
132
+ rc = trilogy_sock_wait_write(conn->socket);
133
+
134
+ if (rc != TRILOGY_OK) {
135
+ return rc;
136
+ }
137
+
138
+ rc = trilogy_flush_writes(conn);
139
+ }
140
+
141
+ return rc;
142
+ }
143
+
144
+ static int read_packet_blocking(trilogy_conn_t *conn)
121
145
  {
122
146
  int rc;
123
147
 
148
+ while ((rc = read_packet(conn)) == TRILOGY_AGAIN) {
149
+ rc = trilogy_sock_wait_read(conn->socket);
150
+
151
+ if (rc != TRILOGY_OK) {
152
+ return rc;
153
+ }
154
+ }
155
+
156
+ return rc;
157
+ }
158
+
159
+ int trilogy_init_no_buffer(trilogy_conn_t *conn)
160
+ {
124
161
  conn->affected_rows = 0;
125
162
  conn->last_insert_id = 0;
126
163
  conn->warning_count = 0;
@@ -142,8 +179,14 @@ int trilogy_init(trilogy_conn_t *conn)
142
179
  trilogy_packet_parser_init(&conn->packet_parser, &packet_parser_callbacks);
143
180
  conn->packet_parser.user_data = &conn->packet_buffer;
144
181
 
145
- CHECKED(trilogy_buffer_init(&conn->packet_buffer, TRILOGY_DEFAULT_BUF_SIZE));
182
+ return TRILOGY_OK;
183
+ }
146
184
 
185
+ int trilogy_init(trilogy_conn_t *conn)
186
+ {
187
+ int rc;
188
+ trilogy_init_no_buffer(conn);
189
+ CHECKED(trilogy_buffer_init(&conn->packet_buffer, TRILOGY_DEFAULT_BUF_SIZE));
147
190
  return TRILOGY_OK;
148
191
  }
149
192
 
@@ -217,7 +260,7 @@ static int read_err_packet(trilogy_conn_t *conn)
217
260
  return TRILOGY_ERR;
218
261
  }
219
262
 
220
- static int read_eof_packet(trilogy_conn_t *conn)
263
+ static int read_deprecated_eof_packet(trilogy_conn_t *conn)
221
264
  {
222
265
  trilogy_eof_packet_t eof_packet;
223
266
 
@@ -236,6 +279,21 @@ static int read_eof_packet(trilogy_conn_t *conn)
236
279
  return TRILOGY_EOF;
237
280
  }
238
281
 
282
+ static int read_eof_packet(trilogy_conn_t *conn)
283
+ {
284
+ int rc;
285
+
286
+ if (conn->capabilities & TRILOGY_CAPABILITIES_DEPRECATE_EOF) {
287
+ return read_ok_packet(conn);
288
+ } else {
289
+ if ((rc = read_deprecated_eof_packet(conn)) != TRILOGY_EOF) {
290
+ return rc;
291
+ }
292
+
293
+ return TRILOGY_OK;
294
+ }
295
+ }
296
+
239
297
  static int read_auth_switch_packet(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
240
298
  {
241
299
  trilogy_auth_switch_request_packet_t auth_switch_packet;
@@ -259,7 +317,8 @@ static int read_auth_switch_packet(trilogy_conn_t *conn, trilogy_handshake_t *ha
259
317
  return TRILOGY_AUTH_SWITCH;
260
318
  }
261
319
 
262
- static int handle_generic_response(trilogy_conn_t *conn) {
320
+ static int handle_generic_response(trilogy_conn_t *conn)
321
+ {
263
322
  switch (current_packet_type(conn)) {
264
323
  case TRILOGY_PACKET_OK:
265
324
  return read_ok_packet(conn);
@@ -310,6 +369,16 @@ int trilogy_connect_send_socket(trilogy_conn_t *conn, trilogy_sock_t *sock)
310
369
  return TRILOGY_OK;
311
370
  }
312
371
 
372
+ int trilogy_connect_set_fd(trilogy_conn_t *conn, trilogy_sock_t *sock, int fd)
373
+ {
374
+ trilogy_sock_set_fd(sock, fd);
375
+
376
+ conn->socket = sock;
377
+ conn->packet_parser.sequence_number = 0;
378
+
379
+ return TRILOGY_OK;
380
+ }
381
+
313
382
  int trilogy_connect_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake_out)
314
383
  {
315
384
  int rc = read_packet(conn);
@@ -407,9 +476,294 @@ void trilogy_auth_clear_password(trilogy_conn_t *conn)
407
476
  }
408
477
  }
409
478
 
479
+ #define CACHING_SHA2_REQUEST_PUBLIC_KEY 2
480
+ #define CACHING_SHA2_SCRAMBLE_LEN 20
410
481
  #define FAST_AUTH_OK 3
411
482
  #define FAST_AUTH_FAIL 4
412
483
 
484
+ static int read_auth_result(trilogy_conn_t *conn)
485
+ {
486
+ int rc = read_packet_blocking(conn);
487
+
488
+ if (rc < 0) {
489
+ return rc;
490
+ }
491
+
492
+ trilogy_auth_clear_password(conn);
493
+ return handle_generic_response(conn);
494
+ }
495
+
496
+ static int send_cleartext_password(trilogy_conn_t *conn)
497
+ {
498
+ trilogy_builder_t builder;
499
+
500
+ int rc = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
501
+
502
+ if (rc < 0) {
503
+ return rc;
504
+ }
505
+
506
+ if (conn->socket->opts.password_len == 0) {
507
+ rc = trilogy_builder_write_uint8(&builder, 0);
508
+
509
+ if (rc < 0) {
510
+ return rc;
511
+ }
512
+
513
+ trilogy_builder_finalize(&builder);
514
+ return flush_current_packet(conn);
515
+ }
516
+
517
+ rc = trilogy_build_auth_clear_password(&builder, conn->socket->opts.password, conn->socket->opts.password_len);
518
+
519
+ if (rc < 0) {
520
+ return rc;
521
+ }
522
+
523
+ return flush_current_packet(conn);
524
+ }
525
+
526
+ static int send_auth_buffer(trilogy_conn_t *conn, const void *buff, size_t buff_len)
527
+ {
528
+ trilogy_builder_t builder;
529
+ int rc = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
530
+
531
+ if (rc < 0) {
532
+ return rc;
533
+ }
534
+
535
+ rc = trilogy_builder_write_buffer(&builder, buff, buff_len);
536
+ if (rc < 0) {
537
+ return rc;
538
+ }
539
+
540
+ trilogy_builder_finalize(&builder);
541
+
542
+ return flush_current_packet(conn);
543
+ }
544
+
545
+ static int send_public_key_request(trilogy_conn_t *conn)
546
+ {
547
+ uint8_t request = CACHING_SHA2_REQUEST_PUBLIC_KEY;
548
+
549
+ return send_auth_buffer(conn, &request, sizeof(request));
550
+ }
551
+
552
+ static int encrypt_password_with_public_key(const uint8_t *scramble, size_t scramble_len, trilogy_conn_t *conn,
553
+ const uint8_t *key_data, size_t key_data_len, uint8_t **encrypted_out,
554
+ size_t *encrypted_len)
555
+ {
556
+ int rc = TRILOGY_OK;
557
+ uint8_t *ciphertext = NULL;
558
+ size_t ciphertext_len = 0;
559
+
560
+ if (key_data_len == 0 || key_data_len > INT_MAX) {
561
+ return TRILOGY_AUTH_PLUGIN_ERROR;
562
+ }
563
+
564
+ size_t password_len = conn->socket->opts.password_len;
565
+ if (password_len == SIZE_MAX) {
566
+ return TRILOGY_MEM_ERROR;
567
+ }
568
+ size_t plaintext_len = password_len + 1;
569
+ uint8_t *plaintext = malloc(plaintext_len);
570
+
571
+ if (plaintext == NULL) {
572
+ return TRILOGY_MEM_ERROR;
573
+ }
574
+
575
+ if (password_len > 0) {
576
+ memcpy(plaintext, conn->socket->opts.password, password_len);
577
+ }
578
+ plaintext[plaintext_len - 1] = '\0';
579
+
580
+ if (scramble_len > 0) {
581
+ for (size_t i = 0; i < plaintext_len; i++) {
582
+ plaintext[i] ^= scramble[i % scramble_len];
583
+ }
584
+ }
585
+
586
+ BIO *bio = BIO_new_mem_buf((void *)key_data, (int)key_data_len);
587
+ if (bio == NULL) {
588
+ free(plaintext);
589
+ return TRILOGY_OPENSSL_ERR;
590
+ }
591
+
592
+ #if OPENSSL_VERSION_NUMBER >= 0x30000000L
593
+ EVP_PKEY *public_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
594
+ #else
595
+ RSA *public_key = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
596
+ #endif
597
+
598
+ BIO_free(bio);
599
+
600
+ if (public_key == NULL) {
601
+ ERR_clear_error();
602
+ memset(plaintext, 0, plaintext_len);
603
+ free(plaintext);
604
+ return TRILOGY_AUTH_PLUGIN_ERROR;
605
+ }
606
+
607
+ #if OPENSSL_VERSION_NUMBER >= 0x30000000L
608
+ int key_size = EVP_PKEY_get_size(public_key);
609
+ if (key_size <= 0) {
610
+ EVP_PKEY_free(public_key);
611
+ memset(plaintext, 0, plaintext_len);
612
+ free(plaintext);
613
+ return TRILOGY_AUTH_PLUGIN_ERROR;
614
+ }
615
+ ciphertext_len = (size_t)key_size;
616
+ #else
617
+ ciphertext_len = (size_t)RSA_size(public_key);
618
+ #endif
619
+
620
+ /*
621
+ When using RSA_PKCS1_OAEP_PADDING the password length must be less
622
+ than RSA_size(rsa) - 41.
623
+ */
624
+ if (ciphertext_len == 0 || plaintext_len + 41 >= ciphertext_len) {
625
+ #if OPENSSL_VERSION_NUMBER >= 0x30000000L
626
+ EVP_PKEY_free(public_key);
627
+ #else
628
+ RSA_free(public_key);
629
+ #endif
630
+ memset(plaintext, 0, plaintext_len);
631
+ free(plaintext);
632
+ return TRILOGY_AUTH_PLUGIN_ERROR;
633
+ }
634
+
635
+ ciphertext = malloc(ciphertext_len);
636
+
637
+ if (ciphertext == NULL) {
638
+ #if OPENSSL_VERSION_NUMBER >= 0x30000000L
639
+ EVP_PKEY_free(public_key);
640
+ #else
641
+ RSA_free(public_key);
642
+ #endif
643
+ memset(plaintext, 0, plaintext_len);
644
+ free(plaintext);
645
+ return TRILOGY_MEM_ERROR;
646
+ }
647
+
648
+ #if OPENSSL_VERSION_NUMBER >= 0x30000000L
649
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(public_key, NULL);
650
+ if (ctx == NULL || EVP_PKEY_encrypt_init(ctx) <= 0 ||
651
+ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
652
+ rc = TRILOGY_OPENSSL_ERR;
653
+ } else {
654
+ size_t out_len = ciphertext_len;
655
+
656
+ if (EVP_PKEY_encrypt(ctx, ciphertext, &out_len, plaintext, plaintext_len) <= 0) {
657
+ rc = TRILOGY_OPENSSL_ERR;
658
+ } else {
659
+ *encrypted_len = out_len;
660
+ }
661
+ }
662
+
663
+ if (ctx) {
664
+ EVP_PKEY_CTX_free(ctx);
665
+ }
666
+ EVP_PKEY_free(public_key);
667
+ #else
668
+ int out_len = RSA_public_encrypt((int)plaintext_len, plaintext, ciphertext, public_key, RSA_PKCS1_OAEP_PADDING);
669
+ RSA_free(public_key);
670
+
671
+ if (out_len < 0) {
672
+ rc = TRILOGY_OPENSSL_ERR;
673
+ } else {
674
+ *encrypted_len = (size_t)out_len;
675
+ }
676
+ #endif
677
+
678
+ memset(plaintext, 0, plaintext_len);
679
+ free(plaintext);
680
+
681
+ if (rc == TRILOGY_OK) {
682
+ *encrypted_out = ciphertext;
683
+ } else {
684
+ memset(ciphertext, 0, ciphertext_len);
685
+ free(ciphertext);
686
+ }
687
+
688
+ return rc;
689
+ }
690
+
691
+ static int handle_fast_auth_fail(trilogy_conn_t *conn, trilogy_handshake_t *handshake, const uint8_t *auth_data,
692
+ size_t auth_data_len)
693
+ {
694
+ int rc;
695
+ bool use_ssl = (conn->socket->opts.flags & TRILOGY_CAPABILITIES_SSL) != 0;
696
+ bool has_unix_socket = (conn->socket->opts.path != NULL);
697
+
698
+ // No password to send, so we can safely respond even without TLS.
699
+ if (conn->socket->opts.password_len == 0) {
700
+ rc = send_cleartext_password(conn);
701
+ if (rc < 0) {
702
+ return rc;
703
+ }
704
+
705
+ return read_auth_result(conn);
706
+ }
707
+
708
+ if (use_ssl || has_unix_socket) {
709
+ rc = send_cleartext_password(conn);
710
+ if (rc < 0) {
711
+ return rc;
712
+ }
713
+
714
+ return read_auth_result(conn);
715
+ }
716
+
717
+ const uint8_t *public_key_data = NULL;
718
+ size_t public_key_len = 0;
719
+
720
+ if (auth_data_len > 1) {
721
+ public_key_data = auth_data + 1;
722
+ public_key_len = auth_data_len - 1;
723
+ } else {
724
+ rc = send_public_key_request(conn);
725
+ if (rc < 0) {
726
+ return rc;
727
+ }
728
+
729
+ rc = read_packet_blocking(conn);
730
+ if (rc < 0) {
731
+ return rc;
732
+ }
733
+
734
+ if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
735
+ return read_err_packet(conn);
736
+ }
737
+
738
+ if (current_packet_type(conn) != TRILOGY_PACKET_AUTH_MORE_DATA || conn->packet_buffer.len < 2) {
739
+ return TRILOGY_PROTOCOL_VIOLATION;
740
+ }
741
+
742
+ public_key_data = conn->packet_buffer.buff + 1;
743
+ public_key_len = conn->packet_buffer.len - 1;
744
+ }
745
+
746
+ uint8_t *encrypted = NULL;
747
+ size_t encrypted_len = 0;
748
+
749
+ rc = encrypt_password_with_public_key((const uint8_t *)handshake->scramble, CACHING_SHA2_SCRAMBLE_LEN, conn,
750
+ public_key_data, public_key_len, &encrypted, &encrypted_len);
751
+
752
+ if (rc < 0) {
753
+ return rc;
754
+ }
755
+
756
+ rc = send_auth_buffer(conn, encrypted, encrypted_len);
757
+ memset(encrypted, 0, encrypted_len);
758
+ free(encrypted);
759
+
760
+ if (rc < 0) {
761
+ return rc;
762
+ }
763
+
764
+ return read_auth_result(conn);
765
+ }
766
+
413
767
  int trilogy_auth_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
414
768
  {
415
769
  int rc = read_packet(conn);
@@ -420,67 +774,24 @@ int trilogy_auth_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
420
774
 
421
775
  switch (current_packet_type(conn)) {
422
776
  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);
777
+ const uint8_t *auth_data = conn->packet_buffer.buff + 1;
778
+ size_t auth_data_len = conn->packet_buffer.len - 1;
425
779
 
426
- if (!use_ssl && !has_unix_socket) {
427
- return TRILOGY_UNSUPPORTED;
780
+ if (auth_data_len < 1) {
781
+ return TRILOGY_PROTOCOL_VIOLATION;
428
782
  }
429
783
 
430
- uint8_t byte = conn->packet_buffer.buff[1];
784
+ uint8_t byte = auth_data[0];
431
785
  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);
786
+ case FAST_AUTH_OK:
787
+ return read_auth_result(conn);
470
788
 
471
- if (rc == TRILOGY_OK) {
472
- break;
473
- }
474
- else if (rc == TRILOGY_AGAIN) {
475
- rc = trilogy_sock_wait_read(conn->socket);
476
- }
789
+ case FAST_AUTH_FAIL:
790
+ return handle_fast_auth_fail(conn, handshake, auth_data, auth_data_len);
477
791
 
478
- if (rc != TRILOGY_OK) {
479
- return rc;
480
- }
792
+ default:
793
+ return TRILOGY_UNEXPECTED_PACKET;
481
794
  }
482
- trilogy_auth_clear_password(conn);
483
- return handle_generic_response(conn);
484
795
  }
485
796
 
486
797
  case TRILOGY_PACKET_EOF:
@@ -535,7 +846,8 @@ int trilogy_set_option_send(trilogy_conn_t *conn, const uint16_t option)
535
846
  return begin_write(conn);
536
847
  }
537
848
 
538
- int trilogy_set_option_recv(trilogy_conn_t *conn) {
849
+ int trilogy_set_option_recv(trilogy_conn_t *conn)
850
+ {
539
851
  int rc = read_packet(conn);
540
852
 
541
853
  if (rc < 0) {
@@ -555,7 +867,6 @@ int trilogy_set_option_recv(trilogy_conn_t *conn) {
555
867
  }
556
868
  }
557
869
 
558
-
559
870
  int trilogy_ping_send(trilogy_conn_t *conn)
560
871
  {
561
872
  trilogy_builder_t builder;
@@ -646,15 +957,7 @@ static int read_eof(trilogy_conn_t *conn)
646
957
  return rc;
647
958
  }
648
959
 
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
- }
960
+ return read_eof_packet(conn);
658
961
  }
659
962
 
660
963
  int trilogy_read_row(trilogy_conn_t *conn, trilogy_value_t *values_out)
@@ -679,14 +982,12 @@ int trilogy_read_row(trilogy_conn_t *conn, trilogy_value_t *values_out)
679
982
  return rc;
680
983
  }
681
984
 
682
- if (conn->capabilities & TRILOGY_CAPABILITIES_DEPRECATE_EOF && current_packet_type(conn) == TRILOGY_PACKET_EOF) {
683
- if ((rc = read_ok_packet(conn)) != TRILOGY_OK) {
985
+ if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
986
+ if ((rc = read_eof_packet(conn)) != TRILOGY_OK) {
684
987
  return rc;
685
988
  }
686
989
 
687
990
  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
991
  } else if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
691
992
  return read_err_packet(conn);
692
993
  } else {
@@ -717,12 +1018,13 @@ int trilogy_drain_results(trilogy_conn_t *conn)
717
1018
  }
718
1019
 
719
1020
  if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
1021
+ read_eof_packet(conn);
720
1022
  return TRILOGY_OK;
721
1023
  }
722
1024
  }
723
1025
  }
724
1026
 
725
- static uint8_t escape_lookup_table[256] = {
1027
+ static const uint8_t escape_lookup_table[256] = {
726
1028
  ['"'] = '"', ['\0'] = '0', ['\''] = '\'', ['\\'] = '\\', ['\n'] = 'n', ['\r'] = 'r', [26] = 'Z',
727
1029
  };
728
1030
 
@@ -735,28 +1037,40 @@ int trilogy_escape(trilogy_conn_t *conn, const char *str, size_t len, const char
735
1037
 
736
1038
  b->len = 0;
737
1039
 
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];
1040
+ // Escaped string will be at least as large as the source string,
1041
+ // so might as well pre-expand the buffer.
1042
+ CHECKED(trilogy_buffer_expand(b, len));
741
1043
 
742
- if (c == '\'') {
743
- CHECKED(trilogy_buffer_putc(b, '\''));
744
- CHECKED(trilogy_buffer_putc(b, '\''));
1044
+ const uint8_t *cursor = (const uint8_t *)str;
1045
+ const uint8_t *end = cursor + len;
1046
+
1047
+ if (conn->server_status & TRILOGY_SERVER_STATUS_NO_BACKSLASH_ESCAPES) {
1048
+ while (cursor < end) {
1049
+ uint8_t *next_escape = memchr(cursor, '\'', (size_t)(end - cursor));
1050
+ if (next_escape) {
1051
+ CHECKED(trilogy_buffer_write(b, cursor, (size_t)(next_escape - cursor)));
1052
+ CHECKED(trilogy_buffer_write(b, (uint8_t *)"\'\'", 2));
1053
+ cursor = next_escape + 1;
745
1054
  } else {
746
- CHECKED(trilogy_buffer_putc(b, c));
1055
+ CHECKED(trilogy_buffer_write(b, cursor, (size_t)(end - cursor)));
1056
+ break;
747
1057
  }
748
1058
  }
749
1059
  } 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];
1060
+ while (cursor < end) {
1061
+ uint8_t escaped = 0;
1062
+ const uint8_t *start = cursor;
1063
+ while (cursor < end && !(escaped = escape_lookup_table[*cursor])) {
1064
+ cursor++;
1065
+ }
754
1066
 
1067
+ CHECKED(trilogy_buffer_write(b, start, (size_t)(cursor - start)));
755
1068
  if (escaped) {
756
1069
  CHECKED(trilogy_buffer_putc(b, '\\'));
757
1070
  CHECKED(trilogy_buffer_putc(b, escaped));
1071
+ cursor++;
758
1072
  } else {
759
- CHECKED(trilogy_buffer_putc(b, c));
1073
+ break;
760
1074
  }
761
1075
  }
762
1076
  }
@@ -940,20 +1254,18 @@ int trilogy_stmt_bind_data_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt, uint
940
1254
  int trilogy_stmt_read_row(trilogy_conn_t *conn, trilogy_stmt_t *stmt, trilogy_column_packet_t *columns,
941
1255
  trilogy_binary_value_t *values_out)
942
1256
  {
943
- int err = read_packet(conn);
1257
+ int rc = read_packet(conn);
944
1258
 
945
- if (err < 0) {
946
- return err;
1259
+ if (rc < 0) {
1260
+ return rc;
947
1261
  }
948
1262
 
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;
1263
+ if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
1264
+ if ((rc = read_eof_packet(conn)) != TRILOGY_OK) {
1265
+ return rc;
952
1266
  }
953
1267
 
954
1268
  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
1269
  } else if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
958
1270
  return read_err_packet(conn);
959
1271
  } else {
@@ -978,9 +1290,7 @@ int trilogy_stmt_reset_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt)
978
1290
  return begin_write(conn);
979
1291
  }
980
1292
 
981
- int trilogy_stmt_reset_recv(trilogy_conn_t *conn) {
982
- return read_generic_response(conn);
983
- }
1293
+ int trilogy_stmt_reset_recv(trilogy_conn_t *conn) { return read_generic_response(conn); }
984
1294
 
985
1295
  int trilogy_stmt_close_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt)
986
1296
  {
@@ -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
  }