@@ -267,7 +267,7 @@ void mc_FLE2IndexedEncryptedValueV2_destroy(mc_FLE2IndexedEncryptedValueV2_t *ie
267267 _mongocrypt_buffer_cleanup (& iev -> ServerEncryptedValue );
268268 _mongocrypt_buffer_cleanup (& iev -> S_KeyId );
269269
270- for (int i = 0 ; i < iev -> edge_count ; i ++ ) {
270+ for (uint32_t i = 0 ; i < iev -> edge_count ; i ++ ) {
271271 mc_FLE2TagAndEncryptedMetadataBlock_cleanup (& iev -> metadata [i ]);
272272 }
273273
@@ -277,8 +277,8 @@ void mc_FLE2IndexedEncryptedValueV2_destroy(mc_FLE2IndexedEncryptedValueV2_t *ie
277277 bson_free (iev );
278278}
279279
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 ) {
282282 BSON_ASSERT_PARAM (iev );
283283
284284 if (iev -> type == kFLE2IEVTypeInitV2 ) {
@@ -297,7 +297,7 @@ uint8_t mc_FLE2IndexedEncryptedValueV2_get_edge_count(const mc_FLE2IndexedEncryp
297297}
298298
299299bool mc_FLE2IndexedEncryptedValueV2_get_substr_tag_count (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
300- uint8_t * count ,
300+ uint32_t * count ,
301301 mongocrypt_status_t * status ) {
302302 BSON_ASSERT_PARAM (iev );
303303 BSON_ASSERT_PARAM (count );
@@ -319,7 +319,7 @@ bool mc_FLE2IndexedEncryptedValueV2_get_substr_tag_count(const mc_FLE2IndexedEnc
319319}
320320
321321bool mc_FLE2IndexedEncryptedValueV2_get_suffix_tag_count (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
322- uint8_t * count ,
322+ uint32_t * count ,
323323 mongocrypt_status_t * status ) {
324324 BSON_ASSERT_PARAM (iev );
325325 BSON_ASSERT_PARAM (count );
@@ -341,7 +341,7 @@ bool mc_FLE2IndexedEncryptedValueV2_get_suffix_tag_count(const mc_FLE2IndexedEnc
341341}
342342
343343bool mc_FLE2IndexedEncryptedValueV2_get_prefix_tag_count (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
344- uint8_t * count ,
344+ uint32_t * count ,
345345 mongocrypt_status_t * status ) {
346346 BSON_ASSERT_PARAM (iev );
347347 BSON_ASSERT_PARAM (count );
@@ -358,13 +358,13 @@ bool mc_FLE2IndexedEncryptedValueV2_get_prefix_tag_count(const mc_FLE2IndexedEnc
358358 return false;
359359 }
360360
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 );
362362 return true;
363363}
364364
365365bool mc_FLE2IndexedEncryptedValueV2_get_edge (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
366366 mc_FLE2TagAndEncryptedMetadataBlock_t * out ,
367- const uint8_t edge_index ,
367+ const uint32_t edge_index ,
368368 mongocrypt_status_t * status ) {
369369 BSON_ASSERT_PARAM (iev );
370370 BSON_ASSERT_PARAM (out );
@@ -376,7 +376,7 @@ bool mc_FLE2IndexedEncryptedValueV2_get_edge(const mc_FLE2IndexedEncryptedValueV
376376 return false;
377377 }
378378
379- if (iev -> type != kFLE2IEVTypeRangeV2 ) {
379+ if (iev -> type != kFLE2IEVTypeRangeV2 && iev -> type != kFLE2IEVTypeText ) {
380380 CLIENT_ERR ("mc_FLE2IndexedEncryptedValueV2_get_edge must be called with type range" );
381381 return false;
382382 }
@@ -440,7 +440,7 @@ bool mc_FLE2IndexedEncryptedValueV2_get_exact_metadata(const mc_FLE2IndexedEncry
440440
441441bool mc_FLE2IndexedEncryptedValueV2_get_substr_metadata (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
442442 mc_FLE2TagAndEncryptedMetadataBlock_t * out ,
443- const uint8_t block_index ,
443+ const uint32_t block_index ,
444444 mongocrypt_status_t * status ) {
445445 BSON_ASSERT_PARAM (iev );
446446 BSON_ASSERT_PARAM (out );
@@ -470,7 +470,7 @@ bool mc_FLE2IndexedEncryptedValueV2_get_substr_metadata(const mc_FLE2IndexedEncr
470470
471471bool mc_FLE2IndexedEncryptedValueV2_get_suffix_metadata (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
472472 mc_FLE2TagAndEncryptedMetadataBlock_t * out ,
473- const uint8_t block_index ,
473+ const uint32_t block_index ,
474474 mongocrypt_status_t * status ) {
475475 BSON_ASSERT_PARAM (iev );
476476 BSON_ASSERT_PARAM (out );
@@ -500,13 +500,13 @@ bool mc_FLE2IndexedEncryptedValueV2_get_suffix_metadata(const mc_FLE2IndexedEncr
500500
501501bool mc_FLE2IndexedEncryptedValueV2_get_prefix_metadata (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
502502 mc_FLE2TagAndEncryptedMetadataBlock_t * out ,
503- const uint8_t block_index ,
503+ const uint32_t block_index ,
504504 mongocrypt_status_t * status ) {
505505 BSON_ASSERT_PARAM (iev );
506506 BSON_ASSERT_PARAM (out );
507507
508508 // 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 ;
510510 if (!mc_FLE2IndexedEncryptedValueV2_get_prefix_tag_count (iev , & prefix_tag_count , status )) {
511511 return false;
512512 }
@@ -571,14 +571,23 @@ bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev,
571571 if (iev -> type == kFLE2IEVTypeEqualityV2 ) {
572572 iev -> edge_count = 1 ;
573573 } 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 ));
578587 // 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 ) {
580589 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
582591 " + 1" ,
583592 iev -> edge_count ,
584593 iev -> substr_tag_count ,
@@ -588,7 +597,7 @@ bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev,
588597 }
589598 }
590599
591- // Maximum edge_count(255 ) times kMetadataLen(96) fits easily without
600+ // Maximum edge_count(4294967295 ) times kMetadataLen(96) fits easily without
592601 // overflow.
593602 const uint64_t metadata_len = iev -> edge_count * kMetadataLen ;
594603
@@ -607,8 +616,8 @@ bool mc_FLE2IndexedEncryptedValueV2_parse(mc_FLE2IndexedEncryptedValueV2_t *iev,
607616 iev -> metadata = (mc_FLE2TagAndEncryptedMetadataBlock_t * )bson_malloc0 (
608617 iev -> edge_count * sizeof (mc_FLE2TagAndEncryptedMetadataBlock_t ));
609618
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 ++ ) {
612621 _mongocrypt_buffer_t tmp_buf ;
613622
614623 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
624633 // fle_blob_subtype: 1 byte
625634 // S_KeyId: UUID_LEN bytes
626635 // 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
629638 // ServerEncryptedValue: ServerEncryptedValue.len bytes
630639 // 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 ;
634642}
635643
636644bool mc_FLE2IndexedEncryptedValueV2_serialize (const mc_FLE2IndexedEncryptedValueV2_t * iev ,
@@ -658,22 +666,22 @@ bool mc_FLE2IndexedEncryptedValueV2_serialize(const mc_FLE2IndexedEncryptedValue
658666 // Serialize bson_value_type
659667 CHECK_AND_RETURN (mc_writer_write_u8 (& writer , iev -> bson_value_type , status ));
660668
661- if (iev -> type == kFLE2IEVTypeRangeV2 || iev -> type == kFLE2IEVTypeText ) {
669+ if (iev -> type == kFLE2IEVTypeRangeV2 ) {
662670 // 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 ));
669677 }
670678
671679 // Serialize encrypted value
672680 CHECK_AND_RETURN (
673681 mc_writer_write_buffer (& writer , & iev -> ServerEncryptedValue , iev -> ServerEncryptedValue .len , status ));
674682
675683 // Serialize metadata
676- for (int i = 0 ; i < iev -> edge_count ; ++ i ) {
684+ for (uint32_t i = 0 ; i < iev -> edge_count ; ++ i ) {
677685 _mongocrypt_buffer_t tmp_buf ;
678686 _mongocrypt_buffer_init (& tmp_buf );
679687
@@ -744,13 +752,18 @@ static bool validate_for_equality(const mc_FLE2IndexedEncryptedValueV2_t *iev, m
744752static bool validate_for_range (const mc_FLE2IndexedEncryptedValueV2_t * iev , mongocrypt_status_t * status ) {
745753 CHECK (iev -> fle_blob_subtype == MC_SUBTYPE_FLE2IndexedRangeEncryptedValueV2 , "fle_blob_subtype does not match type" );
746754 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+ }
747760 return true;
748761}
749762
750763static bool validate_for_text (const mc_FLE2IndexedEncryptedValueV2_t * iev , mongocrypt_status_t * status ) {
751764 CHECK (iev -> fle_blob_subtype == MC_SUBTYPE_FLE2IndexedTextEncryptedValue , "fle_blob_subtype does not match type" );
752765 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 ,
754767 "edge_count is smaller than substr_tag_count + suffix_tag_count + 1" );
755768 return true;
756769}
@@ -798,7 +811,7 @@ bool mc_FLE2IndexedEncryptedValueV2_validate(const mc_FLE2IndexedEncryptedValueV
798811 CHECK (iev -> ClientValue .len == ClientValueLen , "ClientValue.len was unexpected" );
799812 }
800813 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 ++ ) {
802815 if (!mc_FLE2TagAndEncryptedMetadataBlock_validate (& iev -> metadata [i ], status )) {
803816 return false;
804817 }
0 commit comments