libmongocrypt-helper 1.13.2.0.1001 → 1.14.0.0.1001

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.
Files changed (250) hide show
  1. checksums.yaml +4 -4
  2. data/ext/libmongocrypt/libmongocrypt/CHANGELOG.md +8 -0
  3. data/ext/libmongocrypt/libmongocrypt/CMakeLists.txt +5 -1
  4. data/ext/libmongocrypt/libmongocrypt/CODEOWNERS +4 -1
  5. data/ext/libmongocrypt/libmongocrypt/Earthfile +18 -17
  6. data/ext/libmongocrypt/libmongocrypt/README.md +8 -8
  7. data/ext/libmongocrypt/libmongocrypt/bindings/python/CHANGELOG.rst +7 -0
  8. data/ext/libmongocrypt/libmongocrypt/bindings/python/CONTRIBUTING.md +34 -0
  9. data/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/asynchronous/state_machine.py +6 -2
  10. data/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binding.py +18 -2
  11. data/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/mongocrypt.py +9 -1
  12. data/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/options.py +14 -0
  13. data/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/synchronous/state_machine.py +6 -2
  14. data/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/version.py +1 -1
  15. data/ext/libmongocrypt/libmongocrypt/bindings/python/sbom.json +8 -8
  16. data/ext/libmongocrypt/libmongocrypt/bindings/python/scripts/libmongocrypt-version.txt +1 -0
  17. data/ext/libmongocrypt/libmongocrypt/bindings/python/{release.sh → scripts/release.sh} +9 -3
  18. data/ext/libmongocrypt/libmongocrypt/bindings/python/{synchro.py → scripts/synchro.py} +16 -9
  19. data/ext/libmongocrypt/libmongocrypt/bindings/python/scripts/synchro.sh +8 -0
  20. data/ext/libmongocrypt/libmongocrypt/bindings/python/scripts/update-version.sh +27 -0
  21. data/ext/libmongocrypt/libmongocrypt/bindings/python/scripts/update_binding.py +78 -0
  22. data/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_mongocrypt.py +15 -0
  23. data/ext/libmongocrypt/libmongocrypt/doc/releasing.md +25 -18
  24. data/ext/libmongocrypt/libmongocrypt/etc/calc_release_version.py +39 -13
  25. data/ext/libmongocrypt/libmongocrypt/etc/calc_release_version_selftest.sh +1 -1
  26. data/ext/libmongocrypt/libmongocrypt/etc/cyclonedx.sbom.json +2 -2
  27. data/ext/libmongocrypt/libmongocrypt/kms-message/CMakeLists.txt +1 -1
  28. data/ext/libmongocrypt/libmongocrypt/kms-message/src/hexlify.c +5 -0
  29. data/ext/libmongocrypt/libmongocrypt/kms-message/src/hexlify.h +1 -1
  30. data/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_azure_request.c +1 -1
  31. data/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_gcp_request.c +1 -1
  32. data/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_reader_writer.c +4 -2
  33. data/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_kmip_request.c +1 -2
  34. data/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_message_private.h +5 -1
  35. data/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_request.c +1 -1
  36. data/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_request_opt.c +1 -1
  37. data/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_request_str.c +2 -8
  38. data/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_request_str.h +9 -0
  39. data/ext/libmongocrypt/libmongocrypt/kms-message/src/kms_response_parser.c +0 -1
  40. data/ext/libmongocrypt/libmongocrypt/kms-message/src/sort.c +7 -3
  41. data/ext/libmongocrypt/libmongocrypt/kms-message/src/sort.h +2 -0
  42. data/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kmip_reader_writer.c +8 -1
  43. data/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kms_assert.h +5 -4
  44. data/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kms_azure_online.c +1 -1
  45. data/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kms_gcp_online.c +1 -1
  46. data/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kms_kmip_request.c +4 -0
  47. data/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kms_kmip_response.c +3 -0
  48. data/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kms_kmip_response_parser.c +4 -0
  49. data/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kms_online_util.c +1 -1
  50. data/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kms_online_util.h +1 -1
  51. data/ext/libmongocrypt/libmongocrypt/kms-message/test/test_kms_request.c +39 -39
  52. data/ext/libmongocrypt/libmongocrypt/src/crypto/libcrypto.c +235 -65
  53. data/ext/libmongocrypt/libmongocrypt/src/crypto/none.c +1 -1
  54. data/ext/libmongocrypt/libmongocrypt/src/csfle-markup.cpp +4 -2
  55. data/ext/libmongocrypt/libmongocrypt/src/mc-dec128.h +2 -2
  56. data/ext/libmongocrypt/libmongocrypt/src/mc-dec128.test.cpp +2 -2
  57. data/ext/libmongocrypt/libmongocrypt/src/mc-efc-private.h +1 -4
  58. data/ext/libmongocrypt/libmongocrypt/src/mc-efc.c +9 -11
  59. data/ext/libmongocrypt/libmongocrypt/src/mc-fle-blob-subtype-private.h +1 -0
  60. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder-private.h +10 -8
  61. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder.c +167 -176
  62. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-v2.c +6 -17
  63. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload.c +6 -17
  64. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private-v2.h +1 -1
  65. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-v2.c +25 -26
  66. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload.c +2 -1
  67. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-text-payload-private.h +122 -0
  68. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-text-payload.c +477 -0
  69. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private-v2.h +1 -3
  70. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-v2.c +28 -43
  71. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload.c +6 -17
  72. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-v2.c +6 -5
  73. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev.c +13 -10
  74. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-uev-common.c +3 -2
  75. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds.c +7 -6
  76. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-tag-and-encrypted-metadata-block.c +4 -3
  77. data/ext/libmongocrypt/libmongocrypt/src/mc-optional-private.h +1 -1
  78. data/ext/libmongocrypt/libmongocrypt/src/mc-parse-utils-private.h +27 -0
  79. data/ext/libmongocrypt/libmongocrypt/src/mc-parse-utils.c +48 -0
  80. data/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation-private.h +5 -5
  81. data/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation.c +15 -20
  82. data/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding-private.h +4 -6
  83. data/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding.c +9 -18
  84. data/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-generator.template.h +4 -5
  85. data/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-private.h +5 -9
  86. data/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover.c +14 -19
  87. data/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts-private.h +2 -4
  88. data/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts.c +109 -119
  89. data/ext/libmongocrypt/libmongocrypt/src/mc-reader-private.h +2 -2
  90. data/ext/libmongocrypt/libmongocrypt/src/mc-reader.c +4 -2
  91. data/ext/libmongocrypt/libmongocrypt/src/mc-schema-broker-private.h +0 -3
  92. data/ext/libmongocrypt/libmongocrypt/src/mc-schema-broker.c +4 -14
  93. data/ext/libmongocrypt/libmongocrypt/src/mc-str-encode-string-sets-private.h +1 -1
  94. data/ext/libmongocrypt/libmongocrypt/src/mc-str-encode-string-sets.c +3 -3
  95. data/ext/libmongocrypt/libmongocrypt/src/mc-text-search-str-encode-private.h +8 -1
  96. data/ext/libmongocrypt/libmongocrypt/src/mc-text-search-str-encode.c +78 -2
  97. data/ext/libmongocrypt/libmongocrypt/src/mc-tokens-private.h +34 -16
  98. data/ext/libmongocrypt/libmongocrypt/src/mc-tokens.c +66 -74
  99. data/ext/libmongocrypt/libmongocrypt/src/mc-writer-private.h +1 -1
  100. data/ext/libmongocrypt/libmongocrypt/src/mc-writer.c +4 -2
  101. data/ext/libmongocrypt/libmongocrypt/src/mlib/error.h +1 -1
  102. data/ext/libmongocrypt/libmongocrypt/src/mlib/int128.h +12 -1
  103. data/ext/libmongocrypt/libmongocrypt/src/mlib/int128.test.cpp +5 -0
  104. data/ext/libmongocrypt/libmongocrypt/src/mlib/path.h +5 -5
  105. data/ext/libmongocrypt/libmongocrypt/src/mlib/path.test.c +2 -5
  106. data/ext/libmongocrypt/libmongocrypt/src/mlib/str.h +65 -58
  107. data/ext/libmongocrypt/libmongocrypt/src/mlib/str.test.c +3 -3
  108. data/ext/libmongocrypt/libmongocrypt/src/mlib/thread.h +1 -1
  109. data/ext/libmongocrypt/libmongocrypt/src/mlib/user-check.h +1 -1
  110. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-collinfo-private.h +1 -1
  111. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-collinfo.c +4 -0
  112. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ciphertext-private.h +1 -1
  113. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-crypto-private.h +4 -4
  114. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-crypto.c +29 -25
  115. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-datakey.c +3 -2
  116. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-decrypt.c +6 -3
  117. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-encrypt.c +48 -58
  118. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-rewrap-many-datakey.c +12 -0
  119. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx.c +5 -13
  120. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-dll-private.h +19 -2
  121. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker.c +9 -9
  122. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking-private.h +3 -4
  123. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking.c +285 -89
  124. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts-private.h +0 -2
  125. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts.c +0 -1
  126. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-private.h +1 -1
  127. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-util.c +4 -1
  128. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt.c +47 -31
  129. data/ext/libmongocrypt/libmongocrypt/src/os_posix/os_dll.c +2 -0
  130. data/ext/libmongocrypt/libmongocrypt/src/os_posix/os_mutex.c +1 -1
  131. data/ext/libmongocrypt/libmongocrypt/src/os_win/os_dll.c +3 -1
  132. data/ext/libmongocrypt/libmongocrypt/src/os_win/os_mutex.c +1 -1
  133. data/ext/libmongocrypt/libmongocrypt/src/unicode/case-fold-map.c +1 -1
  134. data/ext/libmongocrypt/libmongocrypt/src/unicode/diacritic-fold-map.c +1 -1
  135. data/ext/libmongocrypt/libmongocrypt/src/unicode/fold.c +1 -1
  136. data/ext/libmongocrypt/libmongocrypt/test/crypt_shared-stub.cpp +0 -14
  137. data/ext/libmongocrypt/libmongocrypt/test/data/compact/success/encrypted-field-config-map.json +6 -1
  138. data/ext/libmongocrypt/libmongocrypt/test/data/explicit-decrypt/FLE2InsertUpdatePayloadV2-RangeV2.json +8 -0
  139. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/date-v2/encrypted-field-map.json +1 -1
  140. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/date-v2/encrypted-payload.json +6 -4
  141. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/date-v2/mongocryptd-reply.json +1 -1
  142. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-precision-v2/encrypted-field-map.json +1 -1
  143. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-precision-v2/encrypted-payload.json +6 -4
  144. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-precision-v2/mongocryptd-reply.json +2 -2
  145. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-v2/encrypted-field-map.json +1 -1
  146. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-v2/encrypted-payload.json +6 -4
  147. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-v2/mongocryptd-reply.json +1 -1
  148. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/double-precision-v2/encrypted-payload.json +14 -6
  149. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/double-v2/encrypted-field-map.json +1 -1
  150. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/double-v2/encrypted-payload.json +6 -4
  151. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/double-v2/mongocryptd-reply.json +1 -1
  152. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int32-v2/encrypted-field-map.json +1 -1
  153. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int32-v2/encrypted-payload.json +6 -4
  154. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int32-v2/mongocryptd-reply.json +1 -1
  155. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int64-v2/encrypted-field-map.json +1 -1
  156. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int64-v2/encrypted-payload.json +6 -4
  157. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int64-v2/mongocryptd-reply.json +1 -1
  158. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range-explicit/double/encrypted-payload-v2.json +1 -1
  159. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range-explicit/double-precision/encrypted-payload-v2.json +1 -1
  160. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range-explicit/int32/encrypted-payload-v2.json +1 -1
  161. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range-explicit/int32-openinterval/encrypted-payload-v2.json +1 -1
  162. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/date-v2/encrypted-field-map.json +1 -1
  163. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/date-v2/encrypted-payload.json +6 -4
  164. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/date-v2/mongocryptd-reply.json +1 -1
  165. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-precision-v2/encrypted-field-map.json +1 -1
  166. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-precision-v2/encrypted-payload.json +6 -4
  167. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-precision-v2/mongocryptd-reply.json +1 -1
  168. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-v2/encrypted-field-map.json +1 -1
  169. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-v2/encrypted-payload.json +6 -4
  170. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-v2/mongocryptd-reply.json +1 -1
  171. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double-precision-v2/encrypted-payload.json +14 -6
  172. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double-v2/encrypted-field-map.json +1 -1
  173. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double-v2/encrypted-payload.json +6 -4
  174. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double-v2/mongocryptd-reply.json +1 -1
  175. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int32-v2/encrypted-field-map.json +1 -1
  176. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int32-v2/encrypted-payload.json +3 -3
  177. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int32-v2/mongocryptd-reply.json +1 -1
  178. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int64-v2/encrypted-field-map.json +1 -1
  179. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int64-v2/encrypted-payload.json +6 -4
  180. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int64-v2/mongocryptd-reply.json +1 -1
  181. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/double/encrypted-payload-v2.json +1 -1
  182. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/double-precision/encrypted-payload-v2.json +1 -1
  183. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/int32/encrypted-payload-v2.json +1 -1
  184. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/sparsity-2/encrypted-payload-v2.json +1 -1
  185. data/ext/libmongocrypt/libmongocrypt/test/data/tokens/mc.json +8 -0
  186. data/ext/libmongocrypt/libmongocrypt/test/data/tokens/server.json +8 -0
  187. data/ext/libmongocrypt/libmongocrypt/test/example-state-machine.c +5 -5
  188. data/ext/libmongocrypt/libmongocrypt/test/test-dll.cpp +11 -5
  189. data/ext/libmongocrypt/libmongocrypt/test/test-gcp-auth.c +2 -2
  190. data/ext/libmongocrypt/libmongocrypt/test/test-mc-efc.c +9 -11
  191. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-encryption-placeholder.c +18 -29
  192. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-find-equality-payload-v2.c +1 -1
  193. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-find-range-payload-v2.c +2 -18
  194. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-find-text-payload.c +320 -0
  195. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iup-v2.c +2 -17
  196. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iup.c +1 -1
  197. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-rfds.c +8 -5
  198. data/ext/libmongocrypt/libmongocrypt/test/test-mc-range-edge-generation.c +6 -10
  199. data/ext/libmongocrypt/libmongocrypt/test/test-mc-range-encoding.c +29 -33
  200. data/ext/libmongocrypt/libmongocrypt/test/test-mc-range-mincover.c +12 -20
  201. data/ext/libmongocrypt/libmongocrypt/test/test-mc-rangeopts.c +5 -20
  202. data/ext/libmongocrypt/libmongocrypt/test/test-mc-reader.c +5 -5
  203. data/ext/libmongocrypt/libmongocrypt/test/test-mc-text-search-str-encode.c +147 -18
  204. data/ext/libmongocrypt/libmongocrypt/test/test-mc-tokens.c +35 -14
  205. data/ext/libmongocrypt/libmongocrypt/test/test-mc-writer.c +10 -10
  206. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.c +3 -7
  207. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert.h +36 -24
  208. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-buffer.c +4 -4
  209. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cache.c +2 -2
  210. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ciphertext.c +13 -13
  211. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cleanup.c +49 -55
  212. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-compact.c +64 -67
  213. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-hooks.c +18 -18
  214. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-std-hooks.c +4 -0
  215. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto.c +4 -3
  216. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-csfle-lib.c +13 -3
  217. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-decrypt.c +31 -13
  218. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-encrypt.c +35 -52
  219. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-rewrap-many-datakey.c +28 -1
  220. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-setopt.c +50 -91
  221. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-datakey.c +1 -1
  222. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-dll.c +7 -4
  223. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-endpoint.c +1 -1
  224. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kek.c +1 -1
  225. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-key-cache.c +3 -5
  226. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kms-ctx.c +2 -2
  227. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-local-kms.c +1 -1
  228. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-log.c +2 -2
  229. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-marking.c +527 -225
  230. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-status.c +1 -1
  231. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.c +45 -56
  232. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.h +12 -3
  233. data/ext/libmongocrypt/libmongocrypt/test/test-named-kms-providers.c +11 -11
  234. data/ext/libmongocrypt/libmongocrypt/test/test-unicode-fold.c +6 -2
  235. data/ext/libmongocrypt/libmongocrypt/test/util/HELP.autogen +1 -1
  236. data/ext/libmongocrypt/libmongocrypt/test/util/csfle.c +1 -1
  237. data/ext/libmongocrypt/libmongocrypt/test/util/util.c +5 -5
  238. data/ext/libmongocrypt/libmongocrypt/test/util/util.h +7 -6
  239. data/lib/libmongocrypt_helper/version.rb +2 -2
  240. metadata +17 -13
  241. data/ext/libmongocrypt/libmongocrypt/bindings/python/libmongocrypt-version.txt +0 -1
  242. data/ext/libmongocrypt/libmongocrypt/bindings/python/strip_header.py +0 -50
  243. data/ext/libmongocrypt/libmongocrypt/bindings/python/update-sbom.sh +0 -14
  244. data/ext/libmongocrypt/libmongocrypt/test/data/cleanup/success/encrypted-payload.json +0 -29
  245. data/ext/libmongocrypt/libmongocrypt/test/data/compact/success/encrypted-payload.json +0 -29
  246. data/ext/libmongocrypt/libmongocrypt/test/data/explicit-decrypt/FLE2EqualityIndexedValueV2.json +0 -8
  247. data/ext/libmongocrypt/libmongocrypt/test/data/explicit-decrypt/FLE2RangeIndexedValueV2.json +0 -8
  248. /data/ext/libmongocrypt/libmongocrypt/bindings/python/{build-manylinux-wheel.sh → scripts/build-manylinux-wheel.sh} +0 -0
  249. /data/ext/libmongocrypt/libmongocrypt/test/data/explicit-decrypt/{FLE2InsertUpdatePayload-with-edges.json → FLE2InsertUpdatePayload-RangeV1.json} +0 -0
  250. /data/ext/libmongocrypt/libmongocrypt/test/data/explicit-decrypt/{FLE2InsertUpdatePayload-with-edges-V2.json → FLE2InsertUpdatePayloadV2-RangeV1.json} +0 -0
@@ -18,10 +18,12 @@
18
18
 
19
19
  #include "bson/bson.h"
20
20
  #include "mc-fle-blob-subtype-private.h"
21
+ #include "mc-fle2-find-text-payload-private.h"
21
22
  #include "mc-tokens-private.h"
22
23
  #include "mongocrypt-buffer-private.h"
23
24
  #include "mongocrypt-ciphertext-private.h"
24
25
  #include "mongocrypt-marking-private.h"
26
+ #include "mongocrypt-private.h"
25
27
  #include "mongocrypt.h"
26
28
  #include "test-mongocrypt-assert.h"
27
29
  #include "test-mongocrypt.h"
@@ -68,8 +70,8 @@ static void test_mongocrypt_marking_parse(_mongocrypt_tester_t *tester) {
68
70
  marking_bson = TMP_BSON("{'a': 2, 'v': 'abc', 'ka': 'alt'}");
69
71
  _make_marking(marking_bson, &marking_buf);
70
72
  _parse_ok(&marking_buf, &marking);
71
- BSON_ASSERT(marking.algorithm == MONGOCRYPT_ENCRYPTION_ALGORITHM_RANDOM);
72
- BSON_ASSERT(0 == strcmp("abc", bson_iter_utf8(&marking.v_iter, NULL)));
73
+ BSON_ASSERT(marking.u.fle1.algorithm == MONGOCRYPT_ENCRYPTION_ALGORITHM_RANDOM);
74
+ BSON_ASSERT(0 == strcmp("abc", bson_iter_utf8(&marking.u.fle1.v_iter, NULL)));
73
75
  _mongocrypt_buffer_cleanup(&marking_buf);
74
76
  _mongocrypt_marking_cleanup(&marking);
75
77
 
@@ -198,36 +200,9 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te
198
200
  mc_optional_int64_t sparsity;
199
201
  const char *expectedError;
200
202
  const char *expectedErrorAtParseTime;
201
- bool disableRangeV2;
202
203
  } testcase_t;
203
204
 
204
205
  testcase_t tests[] = {
205
- {.description = "Range V2 disabled w/ trim factor fails",
206
- .findSpecJSON = RAW_STRING({
207
- "lowerBound" : {"$numberInt" : "7"},
208
- "lbIncluded" : true,
209
- "upperBound" : {"$numberInt" : "32"},
210
- "ubIncluded" : true,
211
- "indexMin" : {"$numberInt" : "0"},
212
- "indexMax" : {"$numberInt" : "32"},
213
- "trimFactor" : 0
214
- }),
215
- .disableRangeV2 = true,
216
- .expectedErrorAtParseTime = "'trimFactor' is not supported for QE range v1"},
217
- {.description = "Range V2 disabled w/ no trim factor succeeds",
218
- .findSpecJSON = RAW_STRING({
219
- "lowerBound" : {"$numberInt" : "7"},
220
- "lbIncluded" : true,
221
- "upperBound" : {"$numberInt" : "32"},
222
- "ubIncluded" : true,
223
- "indexMin" : {"$numberInt" : "0"},
224
- "indexMax" : {"$numberInt" : "32"}
225
- }),
226
- .disableRangeV2 = true,
227
- .expectedMinCover = "000111\n"
228
- "001\n"
229
- "01\n"
230
- "100000\n"},
231
206
  {.description = "Int32 Bounds included",
232
207
  .findSpecJSON = RAW_STRING({
233
208
  "lowerBound" : {"$numberInt" : "7"},
@@ -875,7 +850,7 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te
875
850
  ASSERT(bson_iter_init_find(&findSpecIter, findSpecDoc, "findSpec"));
876
851
 
877
852
  mc_FLE2RangeFindSpec_t findSpec;
878
- bool res = mc_FLE2RangeFindSpec_parse(&findSpec, &findSpecIter, !test->disableRangeV2, status);
853
+ bool res = mc_FLE2RangeFindSpec_parse(&findSpec, &findSpecIter, status);
879
854
  if (test->expectedErrorAtParseTime) {
880
855
  ASSERT(!res);
881
856
  ASSERT_STATUS_CONTAINS(status, test->expectedErrorAtParseTime);
@@ -889,8 +864,7 @@ static void test_mc_get_mincover_from_FLE2RangeFindSpec(_mongocrypt_tester_t *te
889
864
  sparsity = (size_t)test->sparsity.value;
890
865
  }
891
866
 
892
- const bool use_range_v2 = !test->disableRangeV2;
893
- mc_mincover_t *mc = mc_get_mincover_from_FLE2RangeFindSpec(&findSpec, sparsity, status, use_range_v2);
867
+ mc_mincover_t *mc = mc_get_mincover_from_FLE2RangeFindSpec(&findSpec, sparsity, status);
894
868
 
895
869
  if (test->expectedError) {
896
870
  ASSERT(NULL == mc);
@@ -950,7 +924,7 @@ static void get_ciphertext_from_marking_json(_mongocrypt_tester_t *tester,
950
924
  const char *markingJSON,
951
925
  _mongocrypt_ciphertext_t *out) {
952
926
  get_ciphertext_from_marking_json_with_bufs(crypt,
953
- TMP_BSON(markingJSON),
927
+ TMP_BSON_STR(markingJSON),
954
928
  out,
955
929
  TEST_FILE("./test/example/cmd.json"),
956
930
  TEST_BIN(16),
@@ -1089,11 +1063,9 @@ static iupv2_fields_common validate_iupv2_common(bson_t *iup_bson) {
1089
1063
 
1090
1064
  // Assert that the encryptedTokens fields in V2 insert/update ciphertext matches our expectations. Specifically, checks
1091
1065
  // that the length of these fields are what we expect, and that the "isLeaf" token is appended when using range V2.
1092
- static void validate_range_ciphertext(_mongocrypt_ciphertext_t *ciphertext,
1093
- mongocrypt_t *crypt,
1094
- bool useRangeV2,
1095
- uint32_t expectedEdges) {
1096
- uint32_t expectedPLength = useRangeV2 ? (MONGOCRYPT_HMAC_SHA256_LEN + 1) : MONGOCRYPT_HMAC_SHA256_LEN;
1066
+ static void
1067
+ validate_range_ciphertext(_mongocrypt_ciphertext_t *ciphertext, mongocrypt_t *crypt, uint32_t expectedEdges) {
1068
+ uint32_t expectedPLength = (MONGOCRYPT_HMAC_SHA256_LEN + 1);
1097
1069
 
1098
1070
  bson_t ciphertextBSON;
1099
1071
  bson_iter_t iter;
@@ -1109,14 +1081,10 @@ static void validate_range_ciphertext(_mongocrypt_ciphertext_t *ciphertext,
1109
1081
  ASSERT(res.p.len == 16 + expectedPLength);
1110
1082
 
1111
1083
  // validate crypto of 'p'
1112
- if (useRangeV2) {
1113
- uint8_t is_leaf = 255;
1114
- validate_encrypted_token(crypt, &res.p, &res.s, true, &is_leaf);
1115
- // isLeaf byte should be 0.
1116
- ASSERT(is_leaf == 0);
1117
- } else {
1118
- validate_encrypted_token(crypt, &res.p, &res.s, false, NULL);
1119
- }
1084
+ uint8_t is_leaf = 255;
1085
+ validate_encrypted_token(crypt, &res.p, &res.s, true, &is_leaf);
1086
+ // isLeaf byte should be 0.
1087
+ ASSERT(is_leaf == 0);
1120
1088
 
1121
1089
  // 'g' field should be available
1122
1090
  ASSERT(bson_iter_init_find(&iter, &ciphertextBSON, "g"));
@@ -1150,24 +1118,18 @@ static void validate_range_ciphertext(_mongocrypt_ciphertext_t *ciphertext,
1150
1118
  ASSERT_CMPUINT32(encrypted_token_bin.len, ==, 16 + expectedPLength);
1151
1119
  ASSERT_CMPUINT32(esc_token_bin.len, ==, MONGOCRYPT_HMAC_SHA256_LEN);
1152
1120
 
1153
- if (useRangeV2) {
1154
- uint8_t is_leaf = 255;
1155
- validate_encrypted_token(crypt, &encrypted_token_bin, &esc_token_bin, true, &is_leaf);
1156
- // isLeaf byte should be either 0 or 1.
1157
- if (is_leaf == 1) {
1158
- leaf_count++;
1159
- } else {
1160
- ASSERT_CMPUINT8(is_leaf, ==, 0)
1161
- }
1121
+ uint8_t is_leaf = 255;
1122
+ validate_encrypted_token(crypt, &encrypted_token_bin, &esc_token_bin, true, &is_leaf);
1123
+ // isLeaf byte should be either 0 or 1.
1124
+ if (is_leaf == 1) {
1125
+ leaf_count++;
1162
1126
  } else {
1163
- validate_encrypted_token(crypt, &encrypted_token_bin, &esc_token_bin, false, NULL);
1127
+ ASSERT_CMPUINT8(is_leaf, ==, 0);
1164
1128
  }
1165
1129
  }
1166
1130
  ASSERT_CMPSIZE_T(g_count, ==, expectedEdges);
1167
- if (useRangeV2) {
1168
- // There should be exactly one leaf in any insert call.
1169
- ASSERT_CMPSIZE_T(leaf_count, ==, 1);
1170
- }
1131
+ // There should be exactly one leaf in any insert call.
1132
+ ASSERT_CMPSIZE_T(leaf_count, ==, 1);
1171
1133
  bson_destroy(&ciphertextBSON);
1172
1134
  }
1173
1135
 
@@ -1177,25 +1139,7 @@ static void test_mc_marking_to_ciphertext_fle2_range(_mongocrypt_tester_t *teste
1177
1139
  return;
1178
1140
  }
1179
1141
 
1180
- // Test that whether range V2 is enabled or disabled, the ciphertext matches our expectations.
1181
- {
1182
- const char markingJSON[] = RAW_STRING({
1183
- 't' : 1,
1184
- 'a' : 3,
1185
- 'v' : {'min' : 0, 'max' : 7, 'v' : 5},
1186
- 's' : {'$numberLong' : '1'},
1187
- 'cm' : {'$numberLong' : '1'}
1188
- });
1189
- _mongocrypt_ciphertext_t ciphertext;
1190
- _mongocrypt_ciphertext_init(&ciphertext);
1191
- mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1192
-
1193
- get_ciphertext_from_marking_json(tester, crypt, markingJSON, &ciphertext);
1194
-
1195
- validate_range_ciphertext(&ciphertext, crypt, false, 4);
1196
- _mongocrypt_ciphertext_cleanup(&ciphertext);
1197
- mongocrypt_destroy(crypt);
1198
- }
1142
+ // Test that ciphertext matches our expectations.
1199
1143
  {
1200
1144
  const char markingJSON[] = RAW_STRING({
1201
1145
  't' : 1,
@@ -1206,11 +1150,11 @@ static void test_mc_marking_to_ciphertext_fle2_range(_mongocrypt_tester_t *teste
1206
1150
  });
1207
1151
  _mongocrypt_ciphertext_t ciphertext;
1208
1152
  _mongocrypt_ciphertext_init(&ciphertext);
1209
- mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_WITH_RANGE_V2);
1153
+ mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1210
1154
 
1211
1155
  get_ciphertext_from_marking_json(tester, crypt, markingJSON, &ciphertext);
1212
1156
 
1213
- validate_range_ciphertext(&ciphertext, crypt, true, 4);
1157
+ validate_range_ciphertext(&ciphertext, crypt, 4);
1214
1158
  _mongocrypt_ciphertext_cleanup(&ciphertext);
1215
1159
 
1216
1160
  mongocrypt_destroy(crypt);
@@ -1280,13 +1224,13 @@ typedef struct {
1280
1224
  static void validate_text_search_ciphertext(_mongocrypt_tester_t *tester,
1281
1225
  _mongocrypt_ciphertext_t *ciphertext,
1282
1226
  mongocrypt_t *crypt,
1283
- const char *text_value,
1227
+ mc_FLE2TextSearchInsertSpec_t *spec,
1284
1228
  mongocrypt_fle2_placeholder_type_t type,
1285
1229
  uint64_t contention_max,
1286
- text_search_expected_token_counts expected_tag_counts) {
1287
- bson_t iup_bson;
1230
+ text_search_expected_token_counts *expected_tag_counts) {
1231
+ bson_t payload_bson;
1288
1232
  bson_iter_t iter;
1289
- ASSERT(_mongocrypt_buffer_to_bson(&ciphertext->data, &iup_bson));
1233
+ ASSERT(_mongocrypt_buffer_to_bson(&ciphertext->data, &payload_bson));
1290
1234
 
1291
1235
  mc_ServerDataEncryptionLevel1Token_t *sdel1Token = getSDEL1Token(crypt);
1292
1236
  const mongocrypt_binary_t *keyId = TEST_BIN(16); // don't free!
@@ -1296,7 +1240,7 @@ static void validate_text_search_ciphertext(_mongocrypt_tester_t *tester,
1296
1240
  ASSERT_CMPUINT8(ciphertext->original_bson_type, ==, 0); // unset
1297
1241
  ASSERT_CMPUINT32(ciphertext->key_id.len, ==, 0); // unset
1298
1242
 
1299
- iupv2_fields_common res = validate_iupv2_common(&iup_bson);
1243
+ iupv2_fields_common res = validate_iupv2_common(&payload_bson);
1300
1244
 
1301
1245
  // validate u, t, k have correct values
1302
1246
  ASSERT_CMPBYTES(keyId->data, keyId->len, res.u.data, res.u.len);
@@ -1333,8 +1277,8 @@ static void validate_text_search_ciphertext(_mongocrypt_tester_t *tester,
1333
1277
 
1334
1278
  // BSON strings have 5 (4 for size + 1 null terminator) bytes of overhead
1335
1279
  ASSERT_CMPUINT32(pbytes, >=, 5);
1336
- ASSERT_CMPSIZE_T(strlen(text_value), ==, (pbytes - 5));
1337
- ASSERT_STREQUAL(text_value, ((char *)(ptext.data + 4)));
1280
+ ASSERT_CMPSIZE_T(spec->len, ==, (pbytes - 5));
1281
+ ASSERT_STREQUAL(spec->v, ((char *)(ptext.data + 4)));
1338
1282
 
1339
1283
  _mongocrypt_buffer_cleanup(&ptext);
1340
1284
  _mongocrypt_buffer_cleanup(&ctext);
@@ -1344,7 +1288,7 @@ static void validate_text_search_ciphertext(_mongocrypt_tester_t *tester,
1344
1288
  }
1345
1289
 
1346
1290
  // assert b exists with correct fields
1347
- ASSERT(bson_iter_init_find(&iter, &iup_bson, "b"));
1291
+ ASSERT(bson_iter_init_find(&iter, &payload_bson, "b"));
1348
1292
  ASSERT(BSON_ITER_HOLDS_DOCUMENT(&iter));
1349
1293
 
1350
1294
  bson_t b_bson;
@@ -1362,19 +1306,66 @@ static void validate_text_search_ciphertext(_mongocrypt_tester_t *tester,
1362
1306
  size_t tscount = 0;
1363
1307
  ASSERT(bson_iter_init_find(&b_iter, &b_bson, "s"));
1364
1308
  tscount = validate_text_search_token_set_array_common(&b_iter, crypt);
1365
- ASSERT_CMPSIZE_T(expected_tag_counts.substrings, ==, tscount);
1309
+ ASSERT_CMPSIZE_T(expected_tag_counts->substrings, ==, tscount);
1366
1310
 
1367
1311
  ASSERT(bson_iter_init_find(&b_iter, &b_bson, "u"));
1368
1312
  tscount = validate_text_search_token_set_array_common(&b_iter, crypt);
1369
- ASSERT_CMPSIZE_T(expected_tag_counts.suffixes, ==, tscount);
1313
+ ASSERT_CMPSIZE_T(expected_tag_counts->suffixes, ==, tscount);
1370
1314
 
1371
1315
  ASSERT(bson_iter_init_find(&b_iter, &b_bson, "p"));
1372
1316
  tscount = validate_text_search_token_set_array_common(&b_iter, crypt);
1373
- ASSERT_CMPSIZE_T(expected_tag_counts.prefixes, ==, tscount);
1317
+ ASSERT_CMPSIZE_T(expected_tag_counts->prefixes, ==, tscount);
1318
+ } else {
1319
+ ASSERT_CMPUINT8(ciphertext->blob_subtype, ==, MC_SUBTYPE_FLE2FindTextPayload);
1320
+ ASSERT_CMPUINT8(ciphertext->original_bson_type, ==, 0); // unset
1321
+ ASSERT_CMPUINT32(ciphertext->key_id.len, ==, 0); // unset
1322
+ mc_FLE2FindTextPayload_t parsed;
1323
+ mongocrypt_status_t *status = mongocrypt_status_new();
1324
+
1325
+ ASSERT_OK_STATUS(mc_FLE2FindTextPayload_parse(&parsed, &payload_bson, status), status);
1326
+ ASSERT_CMPUINT64(parsed.maxContentionFactor, ==, contention_max);
1327
+ ASSERT(parsed.caseFold == spec->casef);
1328
+ ASSERT(parsed.diacriticFold == spec->diacf);
1329
+
1330
+ bool exact = !(spec->prefix.set || spec->suffix.set || spec->substr.set);
1331
+ ASSERT(parsed.tokenSets.prefix.set == spec->prefix.set);
1332
+ ASSERT(parsed.tokenSets.substring.set == spec->substr.set);
1333
+ ASSERT(parsed.tokenSets.suffix.set == spec->suffix.set);
1334
+ ASSERT(parsed.tokenSets.exact.set == exact);
1335
+ ASSERT(parsed.prefixSpec.set == spec->prefix.set);
1336
+ ASSERT(parsed.substringSpec.set == spec->substr.set);
1337
+ ASSERT(parsed.suffixSpec.set == spec->suffix.set);
1338
+
1339
+ #define CHECK_TOKENS(Type) \
1340
+ if (parsed.tokenSets.Type.set) { \
1341
+ ASSERT_CMPUINT32(parsed.tokenSets.Type.value.edcDerivedToken.len, ==, MONGOCRYPT_HMAC_SHA256_LEN); \
1342
+ ASSERT_CMPUINT32(parsed.tokenSets.Type.value.escDerivedToken.len, ==, MONGOCRYPT_HMAC_SHA256_LEN); \
1343
+ ASSERT_CMPUINT32(parsed.tokenSets.Type.value.serverDerivedFromDataToken.len, ==, MONGOCRYPT_HMAC_SHA256_LEN); \
1344
+ }
1345
+ CHECK_TOKENS(prefix);
1346
+ CHECK_TOKENS(suffix);
1347
+ CHECK_TOKENS(substring);
1348
+ CHECK_TOKENS(exact);
1349
+ #undef CHECK_TOKENS
1350
+ if (parsed.prefixSpec.set) {
1351
+ ASSERT_CMPUINT32(parsed.prefixSpec.value.lb, ==, spec->prefix.value.lb);
1352
+ ASSERT_CMPUINT32(parsed.prefixSpec.value.ub, ==, spec->prefix.value.ub);
1353
+ }
1354
+ if (parsed.suffixSpec.set) {
1355
+ ASSERT_CMPUINT32(parsed.suffixSpec.value.lb, ==, spec->suffix.value.lb);
1356
+ ASSERT_CMPUINT32(parsed.suffixSpec.value.ub, ==, spec->suffix.value.ub);
1357
+ }
1358
+ if (parsed.substringSpec.set) {
1359
+ ASSERT_CMPUINT32(parsed.substringSpec.value.mlen, ==, spec->substr.value.mlen);
1360
+ ASSERT_CMPUINT32(parsed.substringSpec.value.lb, ==, spec->substr.value.lb);
1361
+ ASSERT_CMPUINT32(parsed.substringSpec.value.ub, ==, spec->substr.value.ub);
1362
+ }
1363
+ mongocrypt_status_destroy(status);
1364
+ mc_FLE2FindTextPayload_cleanup(&parsed);
1374
1365
  }
1375
1366
 
1376
1367
  mc_ServerDataEncryptionLevel1Token_destroy(sdel1Token);
1377
- bson_destroy(&iup_bson);
1368
+ bson_destroy(&payload_bson);
1378
1369
  }
1379
1370
 
1380
1371
  static size_t calculate_expected_substring_tag_count(size_t beta, size_t mlen, size_t ub, size_t lb) {
@@ -1408,16 +1399,15 @@ static size_t calculate_expected_nfix_tag_count(size_t beta, size_t ub, size_t l
1408
1399
  }
1409
1400
 
1410
1401
  // Runs _mongocrypt_marking_to_ciphertext to compute the ciphertext for the given marking.
1411
- static bool test_text_search_insert_marking_to_ciphertext(_mongocrypt_tester_t *tester,
1412
- mongocrypt_t *crypt,
1413
- _mongocrypt_ciphertext_t *out,
1414
- const char *test_string,
1415
- int test_string_len,
1416
- int mlen,
1417
- mongocrypt_status_t *status) {
1418
- ASSERT_CMPINT(mlen, >, 0);
1419
-
1402
+ static bool test_text_search_marking_to_ciphertext(_mongocrypt_tester_t *tester,
1403
+ mongocrypt_t *crypt,
1404
+ _mongocrypt_ciphertext_t *out,
1405
+ mongocrypt_fle2_placeholder_type_t type,
1406
+ int64_t contention_max,
1407
+ mc_FLE2TextSearchInsertSpec_t *test_spec,
1408
+ mongocrypt_status_t *status) {
1420
1409
  mongocrypt_ctx_t *ctx = mongocrypt_ctx_new(crypt);
1410
+
1421
1411
  // Set up encryption environment
1422
1412
  ASSERT_OK(mongocrypt_ctx_encrypt_init(ctx, "test", -1, TEST_FILE("./test/example/cmd.json")), ctx);
1423
1413
  // Add a test key
@@ -1430,20 +1420,36 @@ static bool test_text_search_insert_marking_to_ciphertext(_mongocrypt_tester_t *
1430
1420
  _mongocrypt_marking_t marking;
1431
1421
 
1432
1422
  bson_t *marking_bson = bson_new();
1433
- BSON_APPEND_INT32(marking_bson, "t", 1);
1434
- BSON_APPEND_INT32(marking_bson, "a", 4);
1435
- BSON_APPEND_INT64(marking_bson, "cm", 2);
1423
+ BSON_APPEND_INT32(marking_bson, "t", type);
1424
+ BSON_APPEND_INT32(marking_bson, "a", MONGOCRYPT_FLE2_ALGORITHM_TEXT_SEARCH);
1425
+ BSON_APPEND_INT64(marking_bson, "cm", contention_max);
1436
1426
  bson_t text_spec;
1437
1427
  BSON_APPEND_DOCUMENT_BEGIN(marking_bson, "v", &text_spec);
1438
- bson_append_utf8(&text_spec, "v", 1, test_string, test_string_len);
1439
- BSON_APPEND_BOOL(&text_spec, "casef", false);
1440
- BSON_APPEND_BOOL(&text_spec, "diacf", false);
1441
- bson_t subspec;
1442
- BSON_APPEND_DOCUMENT_BEGIN(&text_spec, "substr", &subspec);
1443
- BSON_APPEND_INT32(&subspec, "mlen", mlen);
1444
- BSON_APPEND_INT32(&subspec, "ub", 1);
1445
- BSON_APPEND_INT32(&subspec, "lb", 1);
1446
- ASSERT(bson_append_document_end(&text_spec, &subspec));
1428
+ bson_append_utf8(&text_spec, "v", 1, test_spec->v, test_spec->len);
1429
+ BSON_APPEND_BOOL(&text_spec, "casef", test_spec->casef);
1430
+ BSON_APPEND_BOOL(&text_spec, "diacf", test_spec->diacf);
1431
+ if (test_spec->prefix.set) {
1432
+ bson_t subspec;
1433
+ BSON_APPEND_DOCUMENT_BEGIN(&text_spec, "prefix", &subspec);
1434
+ BSON_APPEND_INT32(&subspec, "ub", test_spec->prefix.value.ub);
1435
+ BSON_APPEND_INT32(&subspec, "lb", test_spec->prefix.value.lb);
1436
+ ASSERT(bson_append_document_end(&text_spec, &subspec));
1437
+ }
1438
+ if (test_spec->substr.set) {
1439
+ bson_t subspec;
1440
+ BSON_APPEND_DOCUMENT_BEGIN(&text_spec, "substr", &subspec);
1441
+ BSON_APPEND_INT32(&subspec, "mlen", test_spec->substr.value.mlen);
1442
+ BSON_APPEND_INT32(&subspec, "ub", test_spec->substr.value.ub);
1443
+ BSON_APPEND_INT32(&subspec, "lb", test_spec->substr.value.lb);
1444
+ ASSERT(bson_append_document_end(&text_spec, &subspec));
1445
+ }
1446
+ if (test_spec->suffix.set) {
1447
+ bson_t subspec;
1448
+ BSON_APPEND_DOCUMENT_BEGIN(&text_spec, "suffix", &subspec);
1449
+ BSON_APPEND_INT32(&subspec, "ub", test_spec->suffix.value.ub);
1450
+ BSON_APPEND_INT32(&subspec, "lb", test_spec->suffix.value.lb);
1451
+ ASSERT(bson_append_document_end(&text_spec, &subspec));
1452
+ }
1447
1453
  ASSERT(bson_append_document_end(marking_bson, &text_spec));
1448
1454
 
1449
1455
  // Add key identifier info to the marking
@@ -1471,99 +1477,104 @@ static void test_mc_marking_to_ciphertext_fle2_text_search(_mongocrypt_tester_t
1471
1477
 
1472
1478
  // Test substring
1473
1479
  {
1474
- const char *markingJSON = RAW_STRING({
1475
- 't' : 1,
1476
- 'a' : 4,
1477
- 'v' : {
1478
- 'v' : "foobar",
1479
- 'casef' : false,
1480
- 'diacf' : false,
1481
- 'substr' :
1482
- {'mlen' : {'$numberInt' : '1000'}, 'ub' : {'$numberInt' : '100'}, 'lb' : {'$numberInt' : '10'}}
1483
- },
1484
- 'cm' : {'$numberLong' : '2'}
1485
- });
1486
1480
  _mongocrypt_ciphertext_t ciphertext;
1487
1481
  _mongocrypt_ciphertext_init(&ciphertext);
1488
1482
  mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1483
+ mongocrypt_status_t *status = mongocrypt_status_new();
1484
+ mc_FLE2TextSearchInsertSpec_t spec = {.v = "foobar",
1485
+ .len = 6,
1486
+ .substr.set = true,
1487
+ .substr.value = {.mlen = 1000, .ub = 100, .lb = 10}};
1489
1488
  text_search_expected_token_counts counts = {0};
1490
1489
  counts.substrings = calculate_expected_substring_tag_count(6, 1000, 100, 10);
1491
1490
 
1492
- get_ciphertext_from_marking_json(tester, crypt, markingJSON, &ciphertext);
1491
+ ASSERT_OK_STATUS(test_text_search_marking_to_ciphertext(tester,
1492
+ crypt,
1493
+ &ciphertext,
1494
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1495
+ 2,
1496
+ &spec,
1497
+ status),
1498
+ status);
1493
1499
  validate_text_search_ciphertext(tester,
1494
1500
  &ciphertext,
1495
1501
  crypt,
1496
- "foobar",
1502
+ &spec,
1497
1503
  MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1498
1504
  2,
1499
- counts);
1505
+ &counts);
1500
1506
 
1507
+ mongocrypt_status_destroy(status);
1501
1508
  mongocrypt_destroy(crypt);
1502
1509
  _mongocrypt_ciphertext_cleanup(&ciphertext);
1503
1510
  }
1504
1511
 
1505
1512
  // Test suffix + prefix
1506
1513
  {
1507
- const char *markingJSON = RAW_STRING({
1508
- 't' : 1,
1509
- 'a' : 4,
1510
- 'v' : {
1511
- 'v' : "foobar",
1512
- 'casef' : false,
1513
- 'diacf' : false,
1514
- 'suffix' : {'ub' : {'$numberInt' : '100'}, 'lb' : {'$numberInt' : '10'}},
1515
- 'prefix' : {'ub' : {'$numberInt' : '100'}, 'lb' : {'$numberInt' : '10'}}
1516
- },
1517
- 'cm' : {'$numberLong' : '2'}
1518
- });
1519
1514
  _mongocrypt_ciphertext_t ciphertext;
1520
1515
  _mongocrypt_ciphertext_init(&ciphertext);
1521
1516
  mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1517
+ mongocrypt_status_t *status = mongocrypt_status_new();
1518
+ mc_FLE2TextSearchInsertSpec_t spec = {.v = "foobar",
1519
+ .len = 6,
1520
+ .suffix.set = true,
1521
+ .suffix.value = {.ub = 100, .lb = 10},
1522
+ .prefix.set = true,
1523
+ .prefix.value = {.ub = 100, .lb = 10}};
1522
1524
  text_search_expected_token_counts counts = {0};
1523
1525
  counts.suffixes = counts.prefixes = calculate_expected_nfix_tag_count(6, 100, 10);
1524
1526
 
1525
- get_ciphertext_from_marking_json(tester, crypt, markingJSON, &ciphertext);
1527
+ ASSERT_OK_STATUS(test_text_search_marking_to_ciphertext(tester,
1528
+ crypt,
1529
+ &ciphertext,
1530
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1531
+ 2,
1532
+ &spec,
1533
+ status),
1534
+ status);
1526
1535
  validate_text_search_ciphertext(tester,
1527
1536
  &ciphertext,
1528
1537
  crypt,
1529
- "foobar",
1538
+ &spec,
1530
1539
  MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1531
1540
  2,
1532
- counts);
1533
-
1541
+ &counts);
1542
+ mongocrypt_status_destroy(status);
1534
1543
  mongocrypt_destroy(crypt);
1535
1544
  _mongocrypt_ciphertext_cleanup(&ciphertext);
1536
1545
  }
1537
1546
 
1538
1547
  // Test empty string
1539
1548
  {
1540
- const char *markingJSON = RAW_STRING({
1541
- 't' : 1,
1542
- 'a' : 4,
1543
- 'v' : {
1544
- 'v' : "",
1545
- 'casef' : false,
1546
- 'diacf' : false,
1547
- 'prefix' : {'ub' : {'$numberInt' : '100'}, 'lb' : {'$numberInt' : '10'}}
1548
- },
1549
- 'cm' : {'$numberLong' : '2'}
1550
- });
1551
1549
  _mongocrypt_ciphertext_t ciphertext;
1552
1550
  _mongocrypt_ciphertext_init(&ciphertext);
1553
1551
  mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1552
+ mongocrypt_status_t *status = mongocrypt_status_new();
1553
+ mc_FLE2TextSearchInsertSpec_t spec = {.v = "",
1554
+ .len = 0,
1555
+ .prefix.set = true,
1556
+ .prefix.value = {.ub = 100, .lb = 10}};
1554
1557
  text_search_expected_token_counts counts = {0};
1555
1558
 
1556
1559
  // beta is 1 for empty strings
1557
1560
  counts.prefixes = calculate_expected_nfix_tag_count(1, 100, 10);
1558
1561
 
1559
- get_ciphertext_from_marking_json(tester, crypt, markingJSON, &ciphertext);
1562
+ ASSERT_OK_STATUS(test_text_search_marking_to_ciphertext(tester,
1563
+ crypt,
1564
+ &ciphertext,
1565
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1566
+ 2,
1567
+ &spec,
1568
+ status),
1569
+ status);
1560
1570
  validate_text_search_ciphertext(tester,
1561
1571
  &ciphertext,
1562
1572
  crypt,
1563
- "",
1573
+ &spec,
1564
1574
  MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1565
1575
  2,
1566
- counts);
1576
+ &counts);
1577
+ mongocrypt_status_destroy(status);
1567
1578
  mongocrypt_destroy(crypt);
1568
1579
  _mongocrypt_ciphertext_cleanup(&ciphertext);
1569
1580
  }
@@ -1571,33 +1582,37 @@ static void test_mc_marking_to_ciphertext_fle2_text_search(_mongocrypt_tester_t
1571
1582
  // Test string cbc-padded length is less than lb (ie. substring/suffix/prefix tag sets will be
1572
1583
  // empty)
1573
1584
  {
1574
- const char *markingJSON = RAW_STRING({
1575
- 't' : 1,
1576
- 'a' : 4,
1577
- 'v' : {
1578
- 'v' : "foobar",
1579
- 'casef' : false,
1580
- 'diacf' : false,
1581
- 'substr' :
1582
- {'mlen' : {'$numberInt' : '1000'}, 'ub' : {'$numberInt' : '100'}, 'lb' : {'$numberInt' : '20'}},
1583
- 'prefix' : {'ub' : {'$numberInt' : '100'}, 'lb' : {'$numberInt' : '20'}},
1584
- 'suffix' : {'ub' : {'$numberInt' : '100'}, 'lb' : {'$numberInt' : '20'}}
1585
- },
1586
- 'cm' : {'$numberLong' : '2'}
1587
- });
1588
1585
  _mongocrypt_ciphertext_t ciphertext;
1589
1586
  _mongocrypt_ciphertext_init(&ciphertext);
1590
1587
  mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1588
+ mongocrypt_status_t *status = mongocrypt_status_new();
1589
+ mc_FLE2TextSearchInsertSpec_t spec = {.v = "foobar",
1590
+ .len = 6,
1591
+ .substr.set = true,
1592
+ .substr.value = {.mlen = 1000, .ub = 100, .lb = 20},
1593
+ .prefix.set = true,
1594
+ .prefix.value = {.ub = 100, .lb = 20},
1595
+ .suffix.set = true,
1596
+ .suffix.value = {.ub = 100, .lb = 20}};
1591
1597
  text_search_expected_token_counts counts = {0};
1592
1598
 
1593
- get_ciphertext_from_marking_json(tester, crypt, markingJSON, &ciphertext);
1599
+ ASSERT_OK_STATUS(test_text_search_marking_to_ciphertext(tester,
1600
+ crypt,
1601
+ &ciphertext,
1602
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1603
+ 2,
1604
+ &spec,
1605
+ status),
1606
+ status);
1607
+
1594
1608
  validate_text_search_ciphertext(tester,
1595
1609
  &ciphertext,
1596
1610
  crypt,
1597
- "foobar",
1611
+ &spec,
1598
1612
  MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1599
1613
  2,
1600
- counts);
1614
+ &counts);
1615
+ mongocrypt_status_destroy(status);
1601
1616
  mongocrypt_destroy(crypt);
1602
1617
  _mongocrypt_ciphertext_cleanup(&ciphertext);
1603
1618
  }
@@ -1608,11 +1623,19 @@ static void test_mc_marking_to_ciphertext_fle2_text_search(_mongocrypt_tester_t
1608
1623
  _mongocrypt_ciphertext_init(&ciphertext);
1609
1624
  mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1610
1625
  mongocrypt_status_t *status = mongocrypt_status_new();
1611
-
1612
- ASSERT_FAILS_STATUS(
1613
- test_text_search_insert_marking_to_ciphertext(tester, crypt, &ciphertext, "foobar", 6, 3, status),
1614
- status,
1615
- "longer than the maximum length for substring indexing");
1626
+ mc_FLE2TextSearchInsertSpec_t spec = {.v = "foobar",
1627
+ .len = 6,
1628
+ .substr.set = true,
1629
+ .substr.value = {.mlen = 3, .ub = 1, .lb = 1}};
1630
+ ASSERT_FAILS_STATUS(test_text_search_marking_to_ciphertext(tester,
1631
+ crypt,
1632
+ &ciphertext,
1633
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1634
+ 2,
1635
+ &spec,
1636
+ status),
1637
+ status,
1638
+ "longer than the maximum length for substring indexing");
1616
1639
 
1617
1640
  mongocrypt_status_destroy(status);
1618
1641
  mongocrypt_destroy(crypt);
@@ -1626,37 +1649,46 @@ static void test_mc_marking_to_ciphertext_fle2_text_search(_mongocrypt_tester_t
1626
1649
  mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1627
1650
  const char *expected_msg = "String passed in was not valid UTF-8";
1628
1651
  mongocrypt_status_t *status = mongocrypt_status_new();
1652
+ mc_FLE2TextSearchInsertSpec_t spec = {.v = "foob\xffr",
1653
+ .len = 6,
1654
+ .substr.set = true,
1655
+ .substr.value = {.mlen = INT32_MAX, .ub = 1, .lb = 1}};
1629
1656
 
1630
1657
  // invalid utf-8 byte 0xff
1631
- ASSERT_FAILS_STATUS(test_text_search_insert_marking_to_ciphertext(tester,
1632
- crypt,
1633
- &ciphertext,
1634
- "foob\xffr",
1635
- 6,
1636
- INT32_MAX,
1637
- status),
1658
+ ASSERT_FAILS_STATUS(test_text_search_marking_to_ciphertext(tester,
1659
+ crypt,
1660
+ &ciphertext,
1661
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1662
+ 2,
1663
+ &spec,
1664
+ status),
1638
1665
  status,
1639
1666
  expected_msg);
1640
1667
  _mongocrypt_status_reset(status);
1668
+
1641
1669
  // embedded null byte
1642
- ASSERT_FAILS_STATUS(test_text_search_insert_marking_to_ciphertext(tester,
1643
- crypt,
1644
- &ciphertext,
1645
- "foob\x00r",
1646
- 6,
1647
- INT32_MAX,
1648
- status),
1670
+ spec.v = "foob\x00r";
1671
+ ASSERT_FAILS_STATUS(test_text_search_marking_to_ciphertext(tester,
1672
+ crypt,
1673
+ &ciphertext,
1674
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1675
+ 2,
1676
+ &spec,
1677
+ status),
1649
1678
  status,
1650
1679
  expected_msg);
1651
1680
  _mongocrypt_status_reset(status);
1681
+
1652
1682
  // overlong encoding of 'a' (\x61)
1653
- ASSERT_FAILS_STATUS(test_text_search_insert_marking_to_ciphertext(tester,
1654
- crypt,
1655
- &ciphertext,
1656
- "foob\xE0\x81\xA1r",
1657
- 8,
1658
- INT32_MAX,
1659
- status),
1683
+ spec.v = "foob\xE0\x81\xA1r";
1684
+ spec.len = 8;
1685
+ ASSERT_FAILS_STATUS(test_text_search_marking_to_ciphertext(tester,
1686
+ crypt,
1687
+ &ciphertext,
1688
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1689
+ 2,
1690
+ &spec,
1691
+ status),
1660
1692
  status,
1661
1693
  expected_msg);
1662
1694
 
@@ -1665,26 +1697,30 @@ static void test_mc_marking_to_ciphertext_fle2_text_search(_mongocrypt_tester_t
1665
1697
  _mongocrypt_ciphertext_cleanup(&ciphertext);
1666
1698
  }
1667
1699
 
1668
- // test string is too large
1700
+ // Test string is too large
1669
1701
  {
1670
1702
  _mongocrypt_ciphertext_t ciphertext;
1671
1703
  _mongocrypt_ciphertext_init(&ciphertext);
1672
1704
  mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1673
1705
  const char *expected_msg = "String passed in was too long";
1674
1706
  mongocrypt_status_t *status = mongocrypt_status_new();
1707
+ mc_FLE2TextSearchInsertSpec_t spec = {.substr.set = true,
1708
+ .substr.value = {.mlen = INT32_MAX, .ub = 1, .lb = 1}};
1675
1709
 
1676
1710
  int len = (16 * 1024 * 1024) + 2;
1677
1711
  char *large_str = bson_malloc(len);
1678
1712
  memset(large_str, 'a', len);
1679
1713
  large_str[len - 1] = '\0';
1680
-
1681
- ASSERT_FAILS_STATUS(test_text_search_insert_marking_to_ciphertext(tester,
1682
- crypt,
1683
- &ciphertext,
1684
- large_str,
1685
- len - 1,
1686
- INT32_MAX,
1687
- status),
1714
+ spec.v = large_str;
1715
+ spec.len = len - 1;
1716
+
1717
+ ASSERT_FAILS_STATUS(test_text_search_marking_to_ciphertext(tester,
1718
+ crypt,
1719
+ &ciphertext,
1720
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1721
+ 2,
1722
+ &spec,
1723
+ status),
1688
1724
  status,
1689
1725
  expected_msg);
1690
1726
  bson_free(large_str);
@@ -1692,20 +1728,284 @@ static void test_mc_marking_to_ciphertext_fle2_text_search(_mongocrypt_tester_t
1692
1728
  mongocrypt_destroy(crypt);
1693
1729
  _mongocrypt_ciphertext_cleanup(&ciphertext);
1694
1730
  }
1731
+
1732
+ // Test insert placeholder missing substring/suffix/prefix spec
1733
+ {
1734
+ _mongocrypt_ciphertext_t ciphertext;
1735
+ _mongocrypt_ciphertext_init(&ciphertext);
1736
+ mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1737
+ const char *expected_msg = "missing a substring, suffix, or prefix index specification";
1738
+ mongocrypt_status_t *status = mongocrypt_status_new();
1739
+ mc_FLE2TextSearchInsertSpec_t spec = {.v = "foo", .len = 3};
1740
+ ASSERT_FAILS_STATUS(test_text_search_marking_to_ciphertext(tester,
1741
+ crypt,
1742
+ &ciphertext,
1743
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_INSERT,
1744
+ 2,
1745
+ &spec,
1746
+ status),
1747
+ status,
1748
+ expected_msg);
1749
+ mongocrypt_status_destroy(status);
1750
+ mongocrypt_destroy(crypt);
1751
+ _mongocrypt_ciphertext_cleanup(&ciphertext);
1752
+ }
1753
+
1754
+ // Test find placeholder has multiple query specs
1755
+ {
1756
+ _mongocrypt_ciphertext_t ciphertext;
1757
+ _mongocrypt_ciphertext_init(&ciphertext);
1758
+ mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1759
+ const char *expected_msg = "cannot contain multiple query type specifications";
1760
+ mongocrypt_status_t *status = mongocrypt_status_new();
1761
+ mc_FLE2TextSearchInsertSpec_t spec = {.v = "foo",
1762
+ .len = 3,
1763
+ .substr.set = true,
1764
+ .substr.value = {.mlen = 3, .ub = 1, .lb = 1},
1765
+ .prefix.set = true,
1766
+ .prefix.value = {.ub = 1, .lb = 1}};
1767
+
1768
+ ASSERT_FAILS_STATUS(test_text_search_marking_to_ciphertext(tester,
1769
+ crypt,
1770
+ &ciphertext,
1771
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1772
+ 2,
1773
+ &spec,
1774
+ status),
1775
+ status,
1776
+ expected_msg);
1777
+ mongocrypt_status_destroy(status);
1778
+ mongocrypt_destroy(crypt);
1779
+ _mongocrypt_ciphertext_cleanup(&ciphertext);
1780
+ }
1781
+
1782
+ // Test find placeholder has invalid UTF-8 string
1783
+ {
1784
+ _mongocrypt_ciphertext_t ciphertext;
1785
+ _mongocrypt_ciphertext_init(&ciphertext);
1786
+ mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1787
+ const char *expected_msg = "String passed in was not valid UTF-8";
1788
+ mongocrypt_status_t *status = mongocrypt_status_new();
1789
+ mc_FLE2TextSearchInsertSpec_t spec = {.v = "foob\xffr",
1790
+ .len = 6,
1791
+ .substr.set = true,
1792
+ .substr.value = {.mlen = 50, .ub = 30, .lb = 1}};
1793
+
1794
+ ASSERT_FAILS_STATUS(test_text_search_marking_to_ciphertext(tester,
1795
+ crypt,
1796
+ &ciphertext,
1797
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1798
+ 2,
1799
+ &spec,
1800
+ status),
1801
+ status,
1802
+ expected_msg);
1803
+ mongocrypt_status_destroy(status);
1804
+ mongocrypt_destroy(crypt);
1805
+ _mongocrypt_ciphertext_cleanup(&ciphertext);
1806
+ }
1807
+
1808
+ // Test exact match find
1809
+ {
1810
+ _mongocrypt_ciphertext_t ciphertext;
1811
+ _mongocrypt_ciphertext_init(&ciphertext);
1812
+ mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1813
+ mongocrypt_status_t *status = mongocrypt_status_new();
1814
+ mc_FLE2TextSearchInsertSpec_t spec = {.v = "foo", .len = 3, .diacf = true, .casef = true};
1815
+ ASSERT_OK_STATUS(test_text_search_marking_to_ciphertext(tester,
1816
+ crypt,
1817
+ &ciphertext,
1818
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1819
+ 7,
1820
+ &spec,
1821
+ status),
1822
+ status);
1823
+ validate_text_search_ciphertext(tester,
1824
+ &ciphertext,
1825
+ crypt,
1826
+ &spec,
1827
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1828
+ 7,
1829
+ NULL);
1830
+ _mongocrypt_ciphertext_cleanup(&ciphertext);
1831
+ _mongocrypt_ciphertext_init(&ciphertext);
1832
+
1833
+ // Test empty string case
1834
+ spec.v = "";
1835
+ spec.len = 0;
1836
+ ASSERT_OK_STATUS(test_text_search_marking_to_ciphertext(tester,
1837
+ crypt,
1838
+ &ciphertext,
1839
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1840
+ 7,
1841
+ &spec,
1842
+ status),
1843
+ status);
1844
+ validate_text_search_ciphertext(tester,
1845
+ &ciphertext,
1846
+ crypt,
1847
+ &spec,
1848
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1849
+ 7,
1850
+ NULL);
1851
+
1852
+ mongocrypt_status_destroy(status);
1853
+ mongocrypt_destroy(crypt);
1854
+ _mongocrypt_ciphertext_cleanup(&ciphertext);
1855
+ }
1856
+
1857
+ // Test substring find
1858
+ {
1859
+ _mongocrypt_ciphertext_t ciphertext;
1860
+ _mongocrypt_ciphertext_init(&ciphertext);
1861
+ mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1862
+ mongocrypt_status_t *status = mongocrypt_status_new();
1863
+ mc_FLE2TextSearchInsertSpec_t spec = {.v = "foo",
1864
+ .len = 3,
1865
+ .diacf = true,
1866
+ .substr.set = true,
1867
+ .substr.value = {.mlen = 300, .ub = 200, .lb = 2}};
1868
+ ASSERT_OK_STATUS(test_text_search_marking_to_ciphertext(tester,
1869
+ crypt,
1870
+ &ciphertext,
1871
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1872
+ 8,
1873
+ &spec,
1874
+ status),
1875
+ status);
1876
+ validate_text_search_ciphertext(tester,
1877
+ &ciphertext,
1878
+ crypt,
1879
+ &spec,
1880
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1881
+ 8,
1882
+ NULL);
1883
+ _mongocrypt_ciphertext_cleanup(&ciphertext);
1884
+ _mongocrypt_ciphertext_init(&ciphertext);
1885
+
1886
+ // Test empty string case
1887
+ spec.v = "";
1888
+ spec.len = 0;
1889
+ ASSERT_FAILS_STATUS(test_text_search_marking_to_ciphertext(tester,
1890
+ crypt,
1891
+ &ciphertext,
1892
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1893
+ 8,
1894
+ &spec,
1895
+ status),
1896
+ status,
1897
+ "string value cannot be empty");
1898
+ mongocrypt_status_destroy(status);
1899
+ _mongocrypt_ciphertext_cleanup(&ciphertext);
1900
+ mongocrypt_destroy(crypt);
1901
+ }
1902
+
1903
+ // Test suffix find
1904
+ {
1905
+ _mongocrypt_ciphertext_t ciphertext;
1906
+ _mongocrypt_ciphertext_init(&ciphertext);
1907
+ mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1908
+ mongocrypt_status_t *status = mongocrypt_status_new();
1909
+ mc_FLE2TextSearchInsertSpec_t spec = {.v = "foo",
1910
+ .len = 3,
1911
+ .casef = true,
1912
+ .suffix.set = true,
1913
+ .suffix.value = {.ub = 100, .lb = 1}};
1914
+ ASSERT_OK_STATUS(test_text_search_marking_to_ciphertext(tester,
1915
+ crypt,
1916
+ &ciphertext,
1917
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1918
+ 9,
1919
+ &spec,
1920
+ status),
1921
+ status);
1922
+ validate_text_search_ciphertext(tester,
1923
+ &ciphertext,
1924
+ crypt,
1925
+ &spec,
1926
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1927
+ 9,
1928
+ NULL);
1929
+ _mongocrypt_ciphertext_cleanup(&ciphertext);
1930
+ _mongocrypt_ciphertext_init(&ciphertext);
1931
+
1932
+ // Test empty string case
1933
+ spec.v = "";
1934
+ spec.len = 0;
1935
+ ASSERT_FAILS_STATUS(test_text_search_marking_to_ciphertext(tester,
1936
+ crypt,
1937
+ &ciphertext,
1938
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1939
+ 8,
1940
+ &spec,
1941
+ status),
1942
+ status,
1943
+ "string value cannot be empty");
1944
+ mongocrypt_status_destroy(status);
1945
+ _mongocrypt_ciphertext_cleanup(&ciphertext);
1946
+ mongocrypt_destroy(crypt);
1947
+ }
1948
+
1949
+ // Test prefix find
1950
+ {
1951
+ _mongocrypt_ciphertext_t ciphertext;
1952
+ _mongocrypt_ciphertext_init(&ciphertext);
1953
+ mongocrypt_t *crypt = _mongocrypt_tester_mongocrypt(TESTER_MONGOCRYPT_DEFAULT);
1954
+ mongocrypt_status_t *status = mongocrypt_status_new();
1955
+ mc_FLE2TextSearchInsertSpec_t spec = {.v = "foo",
1956
+ .len = 3,
1957
+ .prefix.set = true,
1958
+ .prefix.value = {.ub = 300, .lb = 3}};
1959
+ ASSERT_OK_STATUS(test_text_search_marking_to_ciphertext(tester,
1960
+ crypt,
1961
+ &ciphertext,
1962
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1963
+ 10,
1964
+ &spec,
1965
+ status),
1966
+ status);
1967
+ validate_text_search_ciphertext(tester,
1968
+ &ciphertext,
1969
+ crypt,
1970
+ &spec,
1971
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1972
+ 10,
1973
+ NULL);
1974
+ _mongocrypt_ciphertext_cleanup(&ciphertext);
1975
+ _mongocrypt_ciphertext_init(&ciphertext);
1976
+
1977
+ // Test empty string case
1978
+ spec.v = "";
1979
+ spec.len = 0;
1980
+ ASSERT_FAILS_STATUS(test_text_search_marking_to_ciphertext(tester,
1981
+ crypt,
1982
+ &ciphertext,
1983
+ MONGOCRYPT_FLE2_PLACEHOLDER_TYPE_FIND,
1984
+ 8,
1985
+ &spec,
1986
+ status),
1987
+ status,
1988
+ "string value cannot be empty");
1989
+ mongocrypt_status_destroy(status);
1990
+ _mongocrypt_ciphertext_cleanup(&ciphertext);
1991
+ mongocrypt_destroy(crypt);
1992
+ }
1695
1993
  }
1696
1994
 
1697
1995
  static void test_ciphertext_len_steps_fle2_text_search(_mongocrypt_tester_t *tester) {
1698
- const char *markingJSONFormat = RAW_STRING({
1699
- 't' : 1,
1700
- 'a' : 4,
1701
- 'v' : {
1702
- 'v' : "%s",
1703
- 'casef' : false,
1704
- 'diacf' : false,
1705
- 'suffix' : {'ub' : {'$numberInt' : '2'}, 'lb' : {'$numberInt' : '1'}}
1706
- },
1707
- 'cm' : {'$numberLong' : '2'}
1708
- });
1996
+ #define MARKING_JSON_FORMAT \
1997
+ RAW_STRING({ \
1998
+ 't' : 1, \
1999
+ 'a' : 4, \
2000
+ 'v' : { \
2001
+ 'v' : "%s", \
2002
+ 'casef' : false, \
2003
+ 'diacf' : false, \
2004
+ 'suffix' : {'ub' : {'$numberInt' : '2'}, 'lb' : {'$numberInt' : '1'}} \
2005
+ }, \
2006
+ 'cm' : {'$numberLong' : '2'} \
2007
+ })
2008
+
1709
2009
  size_t last_len = 0;
1710
2010
  mongocrypt_binary_t *cmd = TEST_FILE("./test/example/cmd.json");
1711
2011
  mongocrypt_binary_t *key_file = TEST_BIN(16);
@@ -1715,10 +2015,10 @@ static void test_ciphertext_len_steps_fle2_text_search(_mongocrypt_tester_t *tes
1715
2015
  for (size_t str_len = 0; str_len < 256; str_len++) {
1716
2016
  char *v = bson_malloc0(str_len + 1);
1717
2017
  memset(v, 'a', str_len);
1718
- size_t bufsize = snprintf(NULL, 0, markingJSONFormat, v) + 1;
2018
+ size_t bufsize = snprintf(NULL, 0, MARKING_JSON_FORMAT, v) + 1;
1719
2019
  char *markingJSON = bson_malloc(bufsize);
1720
- sprintf(markingJSON, markingJSONFormat, v);
1721
- bson_t *marking_bson = TMP_BSON(markingJSON);
2020
+ sprintf(markingJSON, MARKING_JSON_FORMAT, v);
2021
+ bson_t *marking_bson = TMP_BSON_STR(markingJSON);
1722
2022
 
1723
2023
  _mongocrypt_ciphertext_t ciphertext;
1724
2024
  _mongocrypt_ciphertext_init(&ciphertext);
@@ -1750,6 +2050,8 @@ static void test_ciphertext_len_steps_fle2_text_search(_mongocrypt_tester_t *tes
1750
2050
  bson_destroy(marking_bson);
1751
2051
  tester->bson_count--;
1752
2052
  }
2053
+
2054
+ #undef MARKING_JSON_FORMAT
1753
2055
  }
1754
2056
 
1755
2057
  void _mongocrypt_tester_install_marking(_mongocrypt_tester_t *tester) {