2020
2121#include "mc-fle2-encryption-placeholder-private.h"
2222#include "mongocrypt-buffer-private.h"
23+ #include "mongocrypt-private.h"
2324#include "mongocrypt.h"
2425
2526#define CLIENT_ERR_PREFIXED_HELPER (Prefix , ErrorString , ...) CLIENT_ERR(Prefix ": " ErrorString, ##__VA_ARGS__)
4445 goto fail; \
4546 }
4647
48+ // Common logic for parsing int32 greater than zero
49+ #define IF_FIELD_INT32_GT0_PARSE (Name , Dest , Iter ) \
50+ IF_FIELD(Name) { \
51+ if (!BSON_ITER_HOLDS_INT32(&Iter)) { \
52+ CLIENT_ERR_PREFIXED("'" #Name "' must be an int32"); \
53+ goto fail; \
54+ } \
55+ int32_t val = bson_iter_int32(&Iter); \
56+ if (val <= 0) { \
57+ CLIENT_ERR_PREFIXED("'" #Name "' must be greater than zero"); \
58+ goto fail; \
59+ } \
60+ Dest = val; \
61+ } \
62+ END_IF_FIELD
63+
4764void mc_FLE2EncryptionPlaceholder_init (mc_FLE2EncryptionPlaceholder_t * placeholder ) {
4865 memset (placeholder , 0 , sizeof (mc_FLE2EncryptionPlaceholder_t ));
4966}
@@ -94,7 +111,7 @@ bool mc_FLE2EncryptionPlaceholder_parse(mc_FLE2EncryptionPlaceholder_t *out,
94111 }
95112 algorithm = bson_iter_int32 (& iter );
96113 if (algorithm != MONGOCRYPT_FLE2_ALGORITHM_UNINDEXED && algorithm != MONGOCRYPT_FLE2_ALGORITHM_EQUALITY
97- && algorithm != MONGOCRYPT_FLE2_ALGORITHM_RANGE ) {
114+ && algorithm != MONGOCRYPT_FLE2_ALGORITHM_RANGE && algorithm != MONGOCRYPT_FLE2_ALGORITHM_TEXT_SEARCH ) {
98115 CLIENT_ERR_PREFIXED ("invalid algorithm value: %d" , algorithm );
99116 goto fail ;
100117 }
@@ -491,3 +508,203 @@ bool mc_FLE2RangeInsertSpec_parse(mc_FLE2RangeInsertSpec_t *out,
491508}
492509
493510#undef ERROR_PREFIX
511+
512+ #define ERROR_PREFIX "Error parsing FLE2SubstringInsertSpec"
513+
514+ static bool mc_FLE2SubstringInsertSpec_parse (mc_FLE2SubstringInsertSpec_t * out ,
515+ const bson_iter_t * in ,
516+ mongocrypt_status_t * status ) {
517+ bson_iter_t iter ;
518+ bool has_mlen = false, has_ub = false, has_lb = false;
519+ BSON_ASSERT_PARAM (out );
520+ BSON_ASSERT_PARAM (in );
521+
522+ iter = * in ;
523+
524+ if (!BSON_ITER_HOLDS_DOCUMENT (& iter )) {
525+ CLIENT_ERR_PREFIXED ("must be an iterator to a document" );
526+ return false;
527+ }
528+ bson_iter_recurse (& iter , & iter );
529+ while (bson_iter_next (& iter )) {
530+ const char * field = bson_iter_key (& iter );
531+ BSON_ASSERT (field );
532+ IF_FIELD_INT32_GT0_PARSE (mlen , out -> mlen , iter );
533+ IF_FIELD_INT32_GT0_PARSE (ub , out -> ub , iter );
534+ IF_FIELD_INT32_GT0_PARSE (lb , out -> lb , iter );
535+ }
536+ CHECK_HAS (mlen )
537+ CHECK_HAS (ub )
538+ CHECK_HAS (lb )
539+ if (out - > ub < out - > lb ) {
540+ CLIENT_ERR_PREFIXED ("upper bound cannot be less than the lower bound" );
541+ goto fail ;
542+ }
543+ if (out -> mlen < out -> ub ) {
544+ CLIENT_ERR_PREFIXED ("maximum indexed length cannot be less than the upper bound" );
545+ goto fail ;
546+ }
547+ return true;
548+ fail :
549+ return false;
550+ }
551+
552+ #undef ERROR_PREFIX
553+
554+ #define ERROR_PREFIX "Error parsing FLE2SuffixInsertSpec"
555+
556+ static bool
557+ mc_FLE2SuffixInsertSpec_parse (mc_FLE2SuffixInsertSpec_t * out , const bson_iter_t * in , mongocrypt_status_t * status ) {
558+ bson_iter_t iter ;
559+ bool has_ub = false, has_lb = false;
560+
561+ BSON_ASSERT_PARAM (out );
562+ BSON_ASSERT_PARAM (in );
563+
564+ iter = * in ;
565+
566+ if (!BSON_ITER_HOLDS_DOCUMENT (& iter )) {
567+ CLIENT_ERR_PREFIXED ("must be an iterator to a document" );
568+ return false;
569+ }
570+ bson_iter_recurse (& iter , & iter );
571+ while (bson_iter_next (& iter )) {
572+ const char * field = bson_iter_key (& iter );
573+ BSON_ASSERT (field );
574+ IF_FIELD_INT32_GT0_PARSE (ub , out -> ub , iter );
575+ IF_FIELD_INT32_GT0_PARSE (lb , out -> lb , iter );
576+ }
577+ CHECK_HAS (ub )
578+ CHECK_HAS (lb )
579+ if (out - > ub < out - > lb ) {
580+ CLIENT_ERR_PREFIXED ("upper bound cannot be less than the lower bound" );
581+ goto fail ;
582+ }
583+ return true;
584+ fail :
585+ return false;
586+ }
587+
588+ #undef ERROR_PREFIX
589+
590+ #define ERROR_PREFIX "Error parsing FLE2PrefixInsertSpec"
591+
592+ static bool
593+ mc_FLE2PrefixInsertSpec_parse (mc_FLE2PrefixInsertSpec_t * out , const bson_iter_t * in , mongocrypt_status_t * status ) {
594+ bson_iter_t iter ;
595+ bool has_ub = false, has_lb = false;
596+ BSON_ASSERT_PARAM (out );
597+ BSON_ASSERT_PARAM (in );
598+
599+ iter = * in ;
600+
601+ if (!BSON_ITER_HOLDS_DOCUMENT (& iter )) {
602+ CLIENT_ERR_PREFIXED ("must be an iterator to a document" );
603+ return false;
604+ }
605+ bson_iter_recurse (& iter , & iter );
606+ while (bson_iter_next (& iter )) {
607+ const char * field = bson_iter_key (& iter );
608+ BSON_ASSERT (field );
609+ IF_FIELD_INT32_GT0_PARSE (ub , out -> ub , iter );
610+ IF_FIELD_INT32_GT0_PARSE (lb , out -> lb , iter );
611+ }
612+ CHECK_HAS (ub )
613+ CHECK_HAS (lb )
614+ if (out - > ub < out - > lb ) {
615+ CLIENT_ERR_PREFIXED ("upper bound cannot be less than the lower bound" );
616+ goto fail ;
617+ }
618+ fail :
619+ return false;
620+ }
621+
622+ #undef ERROR_PREFIX
623+
624+ #define ERROR_PREFIX "Error parsing FLE2TextSearchInsertSpec"
625+
626+ bool mc_FLE2TextSearchInsertSpec_parse (mc_FLE2TextSearchInsertSpec_t * out ,
627+ const bson_iter_t * in ,
628+ mongocrypt_status_t * status ) {
629+ BSON_ASSERT_PARAM (out );
630+ BSON_ASSERT_PARAM (in );
631+
632+ * out = (mc_FLE2TextSearchInsertSpec_t ){{0 }};
633+
634+ bson_iter_t iter = * in ;
635+ bool has_v = false, has_casef = false, has_diacf = false;
636+ bool has_substr = false, has_suffix = false, has_prefix = false;
637+
638+ if (!BSON_ITER_HOLDS_DOCUMENT (& iter )) {
639+ CLIENT_ERR_PREFIXED ("must be an iterator to a document" );
640+ return false;
641+ }
642+ bson_iter_recurse (& iter , & iter );
643+
644+ while (bson_iter_next (& iter )) {
645+ const char * field = bson_iter_key (& iter );
646+ BSON_ASSERT (field );
647+
648+ IF_FIELD (v ) {
649+ out -> v = iter ;
650+ }
651+ END_IF_FIELD
652+
653+ IF_FIELD (casef ) {
654+ if (!BSON_ITER_HOLDS_BOOL (& iter )) {
655+ CLIENT_ERR_PREFIXED ("'casef' must be a bool" );
656+ goto fail ;
657+ }
658+ out -> casef = bson_iter_bool (& iter );
659+ }
660+ END_IF_FIELD
661+
662+ IF_FIELD (diacf ) {
663+ if (!BSON_ITER_HOLDS_BOOL (& iter )) {
664+ CLIENT_ERR_PREFIXED ("'diacf' must be a bool" );
665+ goto fail ;
666+ }
667+ out -> diacf = bson_iter_bool (& iter );
668+ }
669+ END_IF_FIELD
670+
671+ IF_FIELD (substr ) {
672+ if (!mc_FLE2SubstringInsertSpec_parse (& out -> substringSpec .value , & iter , status )) {
673+ goto fail ;
674+ }
675+ out -> substringSpec .set = true;
676+ }
677+ END_IF_FIELD
678+
679+ IF_FIELD (suffix ) {
680+ if (!mc_FLE2SuffixInsertSpec_parse (& out -> suffixSpec .value , & iter , status )) {
681+ goto fail ;
682+ }
683+ out -> suffixSpec .set = true;
684+ }
685+ END_IF_FIELD
686+
687+ IF_FIELD (prefix ) {
688+ if (!mc_FLE2PrefixInsertSpec_parse (& out -> prefixSpec .value , & iter , status )) {
689+ goto fail ;
690+ }
691+ out -> prefixSpec .set = true;
692+ }
693+ END_IF_FIELD
694+ }
695+
696+ CHECK_HAS (v )
697+ CHECK_HAS (casef )
698+ CHECK_HAS (diacf )
699+ // one of substr/suffix/prefix must be set
700+ if (!(has_substr || has_suffix || has_prefix )) {
701+ CLIENT_ERR_PREFIXED ("Must have a substring, suffix, or prefix index specification" );
702+ goto fail ;
703+ }
704+ return true;
705+
706+ fail :
707+ return false;
708+ }
709+
710+ #undef ERROR_PREFIX
0 commit comments