@@ -267,7 +267,7 @@ void mc_FLE2IndexedEncryptedValueV2_destroy(mc_FLE2IndexedEncryptedValueV2_t *ie
267
267
_mongocrypt_buffer_cleanup (& iev -> ServerEncryptedValue );
268
268
_mongocrypt_buffer_cleanup (& iev -> S_KeyId );
269
269
270
- for (int i = 0 ; i < iev -> edge_count ; i ++ ) {
270
+ for (uint32_t i = 0 ; i < iev -> edge_count ; i ++ ) {
271
271
mc_FLE2TagAndEncryptedMetadataBlock_cleanup (& iev -> metadata [i ]);
272
272
}
273
273
@@ -277,8 +277,8 @@ void mc_FLE2IndexedEncryptedValueV2_destroy(mc_FLE2IndexedEncryptedValueV2_t *ie
277
277
bson_free (iev );
278
278
}
279
279
280
- uint8_t mc_FLE2IndexedEncryptedValueV2_get_edge_count (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
281
- mongocrypt_status_t * status ) {
280
+ uint32_t mc_FLE2IndexedEncryptedValueV2_get_edge_count (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
281
+ mongocrypt_status_t * status ) {
282
282
BSON_ASSERT_PARAM (iev );
283
283
284
284
if (iev -> type == kFLE2IEVTypeInitV2 ) {
@@ -297,7 +297,7 @@ uint8_t mc_FLE2IndexedEncryptedValueV2_get_edge_count(const mc_FLE2IndexedEncryp
297
297
}
298
298
299
299
bool mc_FLE2IndexedEncryptedValueV2_get_substr_tag_count (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
300
- uint8_t * count ,
300
+ uint32_t * count ,
301
301
mongocrypt_status_t * status ) {
302
302
BSON_ASSERT_PARAM (iev );
303
303
BSON_ASSERT_PARAM (count );
@@ -319,7 +319,7 @@ bool mc_FLE2IndexedEncryptedValueV2_get_substr_tag_count(const mc_FLE2IndexedEnc
319
319
}
320
320
321
321
bool mc_FLE2IndexedEncryptedValueV2_get_suffix_tag_count (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
322
- uint8_t * count ,
322
+ uint32_t * count ,
323
323
mongocrypt_status_t * status ) {
324
324
BSON_ASSERT_PARAM (iev );
325
325
BSON_ASSERT_PARAM (count );
@@ -341,7 +341,7 @@ bool mc_FLE2IndexedEncryptedValueV2_get_suffix_tag_count(const mc_FLE2IndexedEnc
341
341
}
342
342
343
343
bool mc_FLE2IndexedEncryptedValueV2_get_prefix_tag_count (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
344
- uint8_t * count ,
344
+ uint32_t * count ,
345
345
mongocrypt_status_t * status ) {
346
346
BSON_ASSERT_PARAM (iev );
347
347
BSON_ASSERT_PARAM (count );
@@ -358,13 +358,13 @@ bool mc_FLE2IndexedEncryptedValueV2_get_prefix_tag_count(const mc_FLE2IndexedEnc
358
358
return false;
359
359
}
360
360
361
- * count = (uint8_t )(iev -> edge_count - iev -> substr_tag_count - iev -> suffix_tag_count - 1 );
361
+ * count = (uint32_t )(iev -> edge_count - iev -> substr_tag_count - iev -> suffix_tag_count - 1 );
362
362
return true;
363
363
}
364
364
365
365
bool mc_FLE2IndexedEncryptedValueV2_get_edge (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
366
366
mc_FLE2TagAndEncryptedMetadataBlock_t * out ,
367
- const uint8_t edge_index ,
367
+ const uint32_t edge_index ,
368
368
mongocrypt_status_t * status ) {
369
369
BSON_ASSERT_PARAM (iev );
370
370
BSON_ASSERT_PARAM (out );
@@ -376,7 +376,7 @@ bool mc_FLE2IndexedEncryptedValueV2_get_edge(const mc_FLE2IndexedEncryptedValueV
376
376
return false;
377
377
}
378
378
379
- if (iev -> type != kFLE2IEVTypeRangeV2 ) {
379
+ if (iev -> type != kFLE2IEVTypeRangeV2 && iev -> type != kFLE2IEVTypeText ) {
380
380
CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_get_edge must be called with type range" );
381
381
return false;
382
382
}
@@ -440,7 +440,7 @@ bool mc_FLE2IndexedEncryptedValueV2_get_exact_metadata(const mc_FLE2IndexedEncry
440
440
441
441
bool mc_FLE2IndexedEncryptedValueV2_get_substr_metadata (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
442
442
mc_FLE2TagAndEncryptedMetadataBlock_t * out ,
443
- const uint8_t block_index ,
443
+ const uint32_t block_index ,
444
444
mongocrypt_status_t * status ) {
445
445
BSON_ASSERT_PARAM (iev );
446
446
BSON_ASSERT_PARAM (out );
@@ -470,7 +470,7 @@ bool mc_FLE2IndexedEncryptedValueV2_get_substr_metadata(const mc_FLE2IndexedEncr
470
470
471
471
bool mc_FLE2IndexedEncryptedValueV2_get_suffix_metadata (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
472
472
mc_FLE2TagAndEncryptedMetadataBlock_t * out ,
473
- const uint8_t block_index ,
473
+ const uint32_t block_index ,
474
474
mongocrypt_status_t * status ) {
475
475
BSON_ASSERT_PARAM (iev );
476
476
BSON_ASSERT_PARAM (out );
@@ -500,13 +500,13 @@ bool mc_FLE2IndexedEncryptedValueV2_get_suffix_metadata(const mc_FLE2IndexedEncr
500
500
501
501
bool mc_FLE2IndexedEncryptedValueV2_get_prefix_metadata (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
502
502
mc_FLE2TagAndEncryptedMetadataBlock_t * out ,
503
- const uint8_t block_index ,
503
+ const uint32_t block_index ,
504
504
mongocrypt_status_t * status ) {
505
505
BSON_ASSERT_PARAM (iev );
506
506
BSON_ASSERT_PARAM (out );
507
507
508
508
// We can skip the check for text type because get_prefix_tag_count does it for us.
509
- uint8_t prefix_tag_count ;
509
+ uint32_t prefix_tag_count ;
510
510
if (!mc_FLE2IndexedEncryptedValueV2_get_prefix_tag_count (iev , & prefix_tag_count , status )) {
511
511
return false;
512
512
}
@@ -571,14 +571,23 @@ bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev,
571
571
if (iev -> type == kFLE2IEVTypeEqualityV2 ) {
572
572
iev -> edge_count = 1 ;
573
573
} else {
574
- CHECK_AND_RETURN (mc_reader_read_u8 (& reader , & iev -> edge_count , status ));
575
- if (iev -> type == kFLE2IEVTypeText ) {
576
- CHECK_AND_RETURN (mc_reader_read_u8 (& reader , & iev -> substr_tag_count , status ));
577
- CHECK_AND_RETURN (mc_reader_read_u8 (& reader , & iev -> suffix_tag_count , status ));
574
+ if (iev -> type == kFLE2IEVTypeRangeV2 ) {
575
+ uint8_t ec ;
576
+ CHECK_AND_RETURN (mc_reader_read_u8 (& reader , & ec , status ));
577
+ if (ec == 0 ) {
578
+ CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_parse edge count must not be 0 for type "
579
+ "range, but found edge count is 0." );
580
+ return false;
581
+ }
582
+ iev -> edge_count = (uint32_t )ec ;
583
+ } else if (iev -> type == kFLE2IEVTypeText ) {
584
+ CHECK_AND_RETURN (mc_reader_read_u32 (& reader , & iev -> edge_count , status ));
585
+ CHECK_AND_RETURN (mc_reader_read_u32 (& reader , & iev -> substr_tag_count , status ));
586
+ CHECK_AND_RETURN (mc_reader_read_u32 (& reader , & iev -> suffix_tag_count , status ));
578
587
// Upconvert so that addition doesn't overflow
579
- if ((uint16_t )iev -> edge_count < (uint16_t )iev -> substr_tag_count + (uint16_t )iev -> suffix_tag_count + 1 ) {
588
+ if ((uint64_t )iev -> edge_count < (uint64_t )iev -> substr_tag_count + (uint64_t )iev -> suffix_tag_count + 1 ) {
580
589
CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_parse for text type expected edge count to be "
581
- "at least substr_tag_count + suffix_count + 1, but: %" PRIu8 " < %" PRIu8 " + %" PRIu8
590
+ "at least substr_tag_count + suffix_count + 1, but: %" PRIu32 " < %" PRIu32 " + %" PRIu32
582
591
" + 1" ,
583
592
iev -> edge_count ,
584
593
iev -> substr_tag_count ,
@@ -588,7 +597,7 @@ bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev,
588
597
}
589
598
}
590
599
591
- // Maximum edge_count(255 ) times kMetadataLen(96) fits easily without
600
+ // Maximum edge_count(4294967295 ) times kMetadataLen(96) fits easily without
592
601
// overflow.
593
602
const uint64_t metadata_len = iev -> edge_count * kMetadataLen ;
594
603
@@ -607,8 +616,8 @@ bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev,
607
616
iev -> metadata = (mc_FLE2TagAndEncryptedMetadataBlock_t * )bson_malloc0 (
608
617
iev -> edge_count * sizeof (mc_FLE2TagAndEncryptedMetadataBlock_t ));
609
618
610
- // Read each metadata element
611
- for (uint8_t i = 0 ; i < iev -> edge_count ; i ++ ) {
619
+ // Read each metadata element in buff
620
+ for (uint32_t i = 0 ; i < iev -> edge_count ; i ++ ) {
612
621
_mongocrypt_buffer_t tmp_buf ;
613
622
614
623
CHECK_AND_RETURN (mc_reader_read_buffer (& reader , & tmp_buf , kMetadataLen , status ));
@@ -624,13 +633,12 @@ static inline uint32_t mc_FLE2IndexedEncryptedValueV2_serialized_length(const mc
624
633
// fle_blob_subtype: 1 byte
625
634
// S_KeyId: UUID_LEN bytes
626
635
// bson_value_type: 1 byte
627
- // if range or text : edge_count: 1 byte
628
- // if text: tag counts: 2 bytes
636
+ // if range: edge_count: 1 byte
637
+ // if text: edge + tag counts: 12 bytes
629
638
// ServerEncryptedValue: ServerEncryptedValue.len bytes
630
639
// metadata: edge_count * kMetadataLen bytes
631
- return iev -> ServerEncryptedValue .len + 1 + UUID_LEN + 1
632
- + (iev -> type == kFLE2IEVTypeRangeV2 || iev -> type == kFLE2IEVTypeText ? 1 : 0 )
633
- + (iev -> type == kFLE2IEVTypeText ? 2 : 0 ) + iev -> edge_count * kMetadataLen ;
640
+ return iev -> ServerEncryptedValue .len + 1 + UUID_LEN + 1 + (iev -> type == kFLE2IEVTypeRangeV2 ? 1 : 0 )
641
+ + (iev -> type == kFLE2IEVTypeText ? 12 : 0 ) + iev -> edge_count * kMetadataLen ;
634
642
}
635
643
636
644
bool mc_FLE2IndexedEncryptedValueV2_serialize (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
@@ -658,22 +666,22 @@ bool mc_FLE2IndexedEncryptedValueV2_serialize(const mc_FLE2IndexedEncryptedValue
658
666
// Serialize bson_value_type
659
667
CHECK_AND_RETURN (mc_writer_write_u8 (& writer , iev -> bson_value_type , status ));
660
668
661
- if (iev -> type == kFLE2IEVTypeRangeV2 || iev -> type == kFLE2IEVTypeText ) {
669
+ if (iev -> type == kFLE2IEVTypeRangeV2 ) {
662
670
// Serialize edge_count (only serialized for types range and text)
663
- CHECK_AND_RETURN (mc_writer_write_u8 (& writer , iev -> edge_count , status ));
664
- if (iev -> type == kFLE2IEVTypeText ) {
665
- // Serialize substr/suffix_tag_count (only serialized for text)
666
- CHECK_AND_RETURN (mc_writer_write_u8 (& writer , iev -> substr_tag_count , status ));
667
- CHECK_AND_RETURN (mc_writer_write_u8 (& writer , iev -> suffix_tag_count , status ));
668
- }
671
+ CHECK_AND_RETURN (mc_writer_write_u8 (& writer , ( uint8_t ) iev -> edge_count , status ));
672
+ } else if (iev -> type == kFLE2IEVTypeText ) {
673
+ // Serialize substr/suffix_tag_count (only serialized for text)
674
+ CHECK_AND_RETURN (mc_writer_write_u32 (& writer , iev -> edge_count , status ));
675
+ CHECK_AND_RETURN (mc_writer_write_u32 (& writer , iev -> substr_tag_count , status ));
676
+ CHECK_AND_RETURN ( mc_writer_write_u32 ( & writer , iev -> suffix_tag_count , status ));
669
677
}
670
678
671
679
// Serialize encrypted value
672
680
CHECK_AND_RETURN (
673
681
mc_writer_write_buffer (& writer , & iev -> ServerEncryptedValue , iev -> ServerEncryptedValue .len , status ));
674
682
675
683
// Serialize metadata
676
- for (int i = 0 ; i < iev -> edge_count ; ++ i ) {
684
+ for (uint32_t i = 0 ; i < iev -> edge_count ; ++ i ) {
677
685
_mongocrypt_buffer_t tmp_buf ;
678
686
_mongocrypt_buffer_init (& tmp_buf );
679
687
@@ -744,13 +752,18 @@ static bool validate_for_equality(const mc_FLE2IndexedEncryptedValueV2_t *iev, m
744
752
static bool validate_for_range (const mc_FLE2IndexedEncryptedValueV2_t * iev , mongocrypt_status_t * status ) {
745
753
CHECK (iev -> fle_blob_subtype == MC_SUBTYPE_FLE2IndexedRangeEncryptedValueV2 , "fle_blob_subtype does not match type" );
746
754
CHECK (is_fle2_range_indexed_supported_type (iev -> bson_value_type ), "bson_value_type is invalid" );
755
+ if (iev -> edge_count > (uint32_t )UINT8_MAX ) {
756
+ CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_validate failed: edge count for range encrypted value "
757
+ "must be less than max uint8_t. Got: %" PRIu32 ,
758
+ iev -> edge_count );
759
+ }
747
760
return true;
748
761
}
749
762
750
763
static bool validate_for_text (const mc_FLE2IndexedEncryptedValueV2_t * iev , mongocrypt_status_t * status ) {
751
764
CHECK (iev -> fle_blob_subtype == MC_SUBTYPE_FLE2IndexedTextEncryptedValue , "fle_blob_subtype does not match type" );
752
765
CHECK (is_fle2_text_indexed_supported_type (iev -> bson_value_type ), "bson_value_type is invalid" );
753
- CHECK ((uint16_t )iev -> edge_count >= (uint16_t )iev -> substr_tag_count + (uint16_t )iev -> suffix_tag_count + 1 ,
766
+ CHECK ((uint64_t )iev -> edge_count >= (uint64_t )iev -> substr_tag_count + (uint64_t )iev -> suffix_tag_count + 1 ,
754
767
"edge_count is smaller than substr_tag_count + suffix_tag_count + 1" );
755
768
return true;
756
769
}
@@ -798,7 +811,7 @@ bool mc_FLE2IndexedEncryptedValueV2_validate(const mc_FLE2IndexedEncryptedValueV
798
811
CHECK (iev -> ClientValue .len == ClientValueLen , "ClientValue.len was unexpected" );
799
812
}
800
813
CHECK (iev -> edge_count > 0 , "edge_count must be at least 1" );
801
- for (uint8_t i = 0 ; i < iev -> edge_count ; i ++ ) {
814
+ for (uint32_t i = 0 ; i < iev -> edge_count ; i ++ ) {
802
815
if (!mc_FLE2TagAndEncryptedMetadataBlock_validate (& iev -> metadata [i ], status )) {
803
816
return false;
804
817
}
0 commit comments