Skip to content

Commit 5ea239b

Browse files
authored
MONGOCRYPT-865 validate sparsity and contention earlier (#1123)
1 parent c2e66c4 commit 5ea239b

10 files changed

Lines changed: 130 additions & 41 deletions

src/mc-fle2-find-equality-payload-v2.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <bson/bson.h>
1818

19+
#include "mc-fle2-encryption-placeholder-private.h"
1920
#include "mc-fle2-find-equality-payload-private-v2.h"
2021
#include "mc-parse-utils-private.h"
2122
#include "mongocrypt-buffer-private.h"
@@ -88,6 +89,9 @@ bool mc_FLE2FindEqualityPayloadV2_parse(mc_FLE2FindEqualityPayloadV2_t *out,
8889
goto fail;
8990
}
9091
out->maxContentionFactor = bson_iter_int64(&iter);
92+
if (!mc_validate_contention(out->maxContentionFactor, status)) {
93+
goto fail;
94+
}
9195
}
9296
END_IF_FIELD
9397
}

src/mc-fle2-find-equality-payload.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <bson/bson.h>
1818

19+
#include "mc-fle2-encryption-placeholder-private.h"
1920
#include "mc-fle2-find-equality-payload-private.h"
2021
#include "mc-parse-utils-private.h"
2122
#include "mongocrypt-buffer-private.h"
@@ -90,6 +91,9 @@ bool mc_FLE2FindEqualityPayload_parse(mc_FLE2FindEqualityPayload_t *out,
9091
goto fail;
9192
}
9293
out->maxContentionFactor = bson_iter_int64(&iter);
94+
if (!mc_validate_contention(out->maxContentionFactor, status)) {
95+
goto fail;
96+
}
9397
}
9498
END_IF_FIELD
9599
}

src/mc-fle2-find-text-payload.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <bson/bson.h>
1818
#include <stdlib.h>
1919

20+
#include "mc-fle2-encryption-placeholder-private.h"
2021
#include "mc-fle2-find-text-payload-private.h"
2122
#include "mc-parse-utils-private.h"
2223
#include "mongocrypt-buffer-private.h"
@@ -315,6 +316,9 @@ bool mc_FLE2FindTextPayload_parse(mc_FLE2FindTextPayload_t *out, const bson_t *i
315316
goto fail;
316317
}
317318
out->maxContentionFactor = bson_iter_int64(&iter);
319+
if (!mc_validate_contention(out->maxContentionFactor, status)) {
320+
goto fail;
321+
}
318322
}
319323
END_IF_FIELD
320324

src/mc-fle2-insert-update-payload-v2.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <bson/bson.h>
1818

19+
#include "mc-fle2-encryption-placeholder-private.h"
1920
#include "mc-fle2-insert-update-payload-private-v2.h"
2021
#include "mc-parse-utils-private.h"
2122
#include "mongocrypt-buffer-private.h"
@@ -205,8 +206,7 @@ bool mc_FLE2InsertUpdatePayloadV2_parse(mc_FLE2InsertUpdatePayloadV2_t *out,
205206
CLIENT_ERR("Field 'k' expected to hold an int64");
206207
goto fail;
207208
}
208-
if ((contention < 0)) {
209-
CLIENT_ERR("Field 'k' must be non-negative, got: %" PRId64, contention);
209+
if (!mc_validate_contention(contention, status)) {
210210
goto fail;
211211
}
212212
out->contentionFactor = contention;
@@ -224,6 +224,9 @@ bool mc_FLE2InsertUpdatePayloadV2_parse(mc_FLE2InsertUpdatePayloadV2_t *out,
224224
goto fail;
225225
}
226226
int64_t sparsity = bson_iter_int64(&iter);
227+
if (!mc_validate_sparsity(sparsity, status)) {
228+
goto fail;
229+
}
227230
out->sparsity = OPT_I64(sparsity);
228231
}
229232
END_IF_FIELD

src/mc-rangeopts.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
#include "mc-fle2-encryption-placeholder-private.h"
1718
#include "mc-rangeopts-private.h"
1819

1920
#include "mc-check-conversions-private.h"
@@ -83,6 +84,9 @@ bool mc_RangeOpts_parse(mc_RangeOpts_t *ro, const bson_t *in, mongocrypt_status_
8384
return false;
8485
}
8586
ro->sparsity = bson_iter_int64(&iter);
87+
if (!mc_validate_sparsity(ro->sparsity, status)) {
88+
return false;
89+
}
8690
}
8791
END_IF_FIELD;
8892

test/test-mc-fle2-find-equality-payload-v2.c

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -74,21 +74,43 @@ static void _test_FLE2FindEqualityPayloadV2_roundtrip(_mongocrypt_tester_t *test
7474
#undef TEST_FIND_EQ_PAYLOAD_HEX_V2
7575

7676
static void _test_FLE2FindEqualityPayloadV2_errors(_mongocrypt_tester_t *tester) {
77-
bson_t *input_bson = TMP_BSON_STR(BSON_STR({
78-
"d" : {"$binary" : {"base64" : "AAAA", "subType" : "00"}},
79-
"s" : {"$binary" : {"base64" : "AAAA", "subType" : "00"}},
80-
"l" : {"$binary" : {"base64" : "AAAA", "subType" : "00"}},
81-
"cm" : "wrong type!"
82-
}));
83-
84-
mc_FLE2FindEqualityPayloadV2_t payload;
85-
mc_FLE2FindEqualityPayloadV2_init(&payload);
86-
mongocrypt_status_t *status = mongocrypt_status_new();
87-
ASSERT_FAILS_STATUS(mc_FLE2FindEqualityPayloadV2_parse(&payload, input_bson, status),
88-
status,
89-
"Field 'cm' expected to hold an int64");
90-
mc_FLE2FindEqualityPayloadV2_cleanup(&payload);
91-
mongocrypt_status_destroy(status);
77+
// Test non-int64 'cm'
78+
{
79+
bson_t *input_bson = TMP_BSON_STR(BSON_STR({
80+
"d" : {"$binary" : {"base64" : "AAAA", "subType" : "00"}},
81+
"s" : {"$binary" : {"base64" : "AAAA", "subType" : "00"}},
82+
"l" : {"$binary" : {"base64" : "AAAA", "subType" : "00"}},
83+
"cm" : "wrong type!"
84+
}));
85+
86+
mc_FLE2FindEqualityPayloadV2_t payload;
87+
mc_FLE2FindEqualityPayloadV2_init(&payload);
88+
mongocrypt_status_t *status = mongocrypt_status_new();
89+
ASSERT_FAILS_STATUS(mc_FLE2FindEqualityPayloadV2_parse(&payload, input_bson, status),
90+
status,
91+
"Field 'cm' expected to hold an int64");
92+
mc_FLE2FindEqualityPayloadV2_cleanup(&payload);
93+
mongocrypt_status_destroy(status);
94+
}
95+
96+
// Test negative 'cm'
97+
{
98+
bson_t *input_bson = TMP_BSON_STR(BSON_STR({
99+
"d" : {"$binary" : {"base64" : "AAAA", "subType" : "00"}},
100+
"s" : {"$binary" : {"base64" : "AAAA", "subType" : "00"}},
101+
"l" : {"$binary" : {"base64" : "AAAA", "subType" : "00"}},
102+
"cm" : {"$numberLong" : "-1"}
103+
}));
104+
105+
mc_FLE2FindEqualityPayloadV2_t payload;
106+
mc_FLE2FindEqualityPayloadV2_init(&payload);
107+
mongocrypt_status_t *status = mongocrypt_status_new();
108+
ASSERT_FAILS_STATUS(mc_FLE2FindEqualityPayloadV2_parse(&payload, input_bson, status),
109+
status,
110+
"must be non-negative");
111+
mc_FLE2FindEqualityPayloadV2_cleanup(&payload);
112+
mongocrypt_status_destroy(status);
113+
}
92114
}
93115

94116
void _mongocrypt_tester_install_fle2_payload_find_equality_v2(_mongocrypt_tester_t *tester) {

test/test-mc-fle2-find-text-payload.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,12 @@ static void _test_FLE2FindTextPayload_parse_errors(_mongocrypt_tester_t *tester)
312312
_do_parse_error_test(tester, level2, "Unrecognized field 'oo'");
313313
_do_parse_error_test(tester, level3, "Unrecognized field 'pp'");
314314
}
315+
316+
// Test invalid contention:
317+
{
318+
bson_t *bad_cm = TMP_BSON("{'cm': {'$numberLong': '-1' }, %s}", TS_JSON ", " CF_JSON ", " DF_JSON);
319+
_do_parse_error_test(tester, bad_cm, "must be non-negative");
320+
}
315321
}
316322

317323
void _mongocrypt_tester_install_fle2_payload_find_text(_mongocrypt_tester_t *tester) {

test/test-mc-fle2-payload-iup-v2.c

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -228,24 +228,65 @@ static void _test_mc_FLE2InsertUpdatePayloadV2_parses_crypto_params(_mongocrypt_
228228
}
229229

230230
static void _test_mc_FLE2InsertUpdatePayloadV2_parse_errors(_mongocrypt_tester_t *tester) {
231-
bson_t *input_bson = TMP_BSON_STR(BSON_STR({
232-
"d" : {"$binary" : {"base64" : "AAAA", "subType" : "00"}}, //
233-
"t" : "wrong type!"
234-
}));
235-
_mongocrypt_buffer_t input_buf;
236-
_mongocrypt_buffer_init_size(&input_buf, 1 + input_bson->len);
237-
input_buf.data[0] = (uint8_t)MC_SUBTYPE_FLE2InsertUpdatePayloadV2;
238-
memcpy(input_buf.data + 1, bson_get_data(input_bson), input_bson->len);
231+
// Test wrong type for 't':
232+
{
233+
bson_t *input_bson = TMP_BSON_STR(BSON_STR({
234+
"d" : {"$binary" : {"base64" : "AAAA", "subType" : "00"}}, //
235+
"t" : "wrong type!"
236+
}));
237+
_mongocrypt_buffer_t input_buf;
238+
_mongocrypt_buffer_init_size(&input_buf, 1 + input_bson->len);
239+
input_buf.data[0] = (uint8_t)MC_SUBTYPE_FLE2InsertUpdatePayloadV2;
240+
memcpy(input_buf.data + 1, bson_get_data(input_bson), input_bson->len);
241+
242+
mc_FLE2InsertUpdatePayloadV2_t payload;
243+
mc_FLE2InsertUpdatePayloadV2_init(&payload);
244+
mongocrypt_status_t *status = mongocrypt_status_new();
245+
ASSERT_FAILS_STATUS(mc_FLE2InsertUpdatePayloadV2_parse(&payload, &input_buf, status),
246+
status,
247+
"Field 't' expected to hold an int32");
248+
mc_FLE2InsertUpdatePayloadV2_cleanup(&payload);
249+
mongocrypt_status_destroy(status);
250+
_mongocrypt_buffer_cleanup(&input_buf);
251+
}
239252

240-
mc_FLE2InsertUpdatePayloadV2_t payload;
241-
mc_FLE2InsertUpdatePayloadV2_init(&payload);
242-
mongocrypt_status_t *status = mongocrypt_status_new();
243-
ASSERT_FAILS_STATUS(mc_FLE2InsertUpdatePayloadV2_parse(&payload, &input_buf, status),
244-
status,
245-
"Field 't' expected to hold an int32");
246-
mc_FLE2InsertUpdatePayloadV2_cleanup(&payload);
247-
mongocrypt_status_destroy(status);
248-
_mongocrypt_buffer_cleanup(&input_buf);
253+
// Test negative 'k':
254+
{
255+
bson_t *input_bson = TMP_BSON_STR(BSON_STR({"k" : {"$numberLong" : "-1"}}));
256+
_mongocrypt_buffer_t input_buf;
257+
_mongocrypt_buffer_init_size(&input_buf, 1 + input_bson->len);
258+
input_buf.data[0] = (uint8_t)MC_SUBTYPE_FLE2InsertUpdatePayloadV2;
259+
memcpy(input_buf.data + 1, bson_get_data(input_bson), input_bson->len);
260+
261+
mc_FLE2InsertUpdatePayloadV2_t payload;
262+
mc_FLE2InsertUpdatePayloadV2_init(&payload);
263+
mongocrypt_status_t *status = mongocrypt_status_new();
264+
ASSERT_FAILS_STATUS(mc_FLE2InsertUpdatePayloadV2_parse(&payload, &input_buf, status),
265+
status,
266+
"contention must be non-negative");
267+
mc_FLE2InsertUpdatePayloadV2_cleanup(&payload);
268+
mongocrypt_status_destroy(status);
269+
_mongocrypt_buffer_cleanup(&input_buf);
270+
}
271+
272+
// Test negative 'sp':
273+
{
274+
bson_t *input_bson = TMP_BSON_STR(BSON_STR({"sp" : {"$numberLong" : "-1"}}));
275+
_mongocrypt_buffer_t input_buf;
276+
_mongocrypt_buffer_init_size(&input_buf, 1 + input_bson->len);
277+
input_buf.data[0] = (uint8_t)MC_SUBTYPE_FLE2InsertUpdatePayloadV2;
278+
memcpy(input_buf.data + 1, bson_get_data(input_bson), input_bson->len);
279+
280+
mc_FLE2InsertUpdatePayloadV2_t payload;
281+
mc_FLE2InsertUpdatePayloadV2_init(&payload);
282+
mongocrypt_status_t *status = mongocrypt_status_new();
283+
ASSERT_FAILS_STATUS(mc_FLE2InsertUpdatePayloadV2_parse(&payload, &input_buf, status),
284+
status,
285+
"sparsity must be non-negative");
286+
mc_FLE2InsertUpdatePayloadV2_cleanup(&payload);
287+
mongocrypt_status_destroy(status);
288+
_mongocrypt_buffer_cleanup(&input_buf);
289+
}
249290
}
250291

251292
void _mongocrypt_tester_install_fle2_payload_iup_v2(_mongocrypt_tester_t *tester) {

test/test-mc-rangeopts.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ static void test_mc_RangeOpts_parse(_mongocrypt_tester_t *tester) {
7373
{.desc = "Errors on negative trim factor",
7474
.in = RAW_STRING({"trimFactor" : -1, "sparsity" : {"$numberLong" : "1"}}),
7575
.expectError = "'trimFactor' must be non-negative"},
76+
{.desc = "Errors on negative sparsity",
77+
.in = RAW_STRING({"sparsity" : {"$numberLong" : "-1"}}),
78+
.expectError = "sparsity must be non-negative"},
7679
};
7780

7881
for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {

test/test-mongocrypt-ctx-setopt.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -874,13 +874,11 @@ static void _test_setopt_for_explicit_encrypt(_mongocrypt_tester_t *tester) {
874874
/* Set key ID to get past the 'either key id or key alt name required'
875875
* error */
876876
ASSERT_KEY_ID_OK(uuid);
877-
ASSERT_OK(mongocrypt_ctx_setopt_algorithm_range(
878-
ctx,
879-
TEST_BSON("{'min': 0, 'max': 1, 'sparsity': { '$numberLong': '-1'}}")),
880-
ctx);
881-
ASSERT_OK(mongocrypt_ctx_setopt_contention_factor(ctx, 0), ctx);
882-
ASSERT_OK(mongocrypt_ctx_setopt_algorithm(ctx, MONGOCRYPT_ALGORITHM_RANGE_STR, -1), ctx);
883-
ASSERT_EX_ENCRYPT_INIT_FAILS(bson, "sparsity must be non-negative");
877+
ASSERT_FAILS(mongocrypt_ctx_setopt_algorithm_range(
878+
ctx,
879+
TEST_BSON("{'min': 0, 'max': 1, 'sparsity': { '$numberLong': '-1'}}")),
880+
ctx,
881+
"sparsity must be non-negative");
884882
}
885883

886884
/* Error if query_type == "range" and algorithm != "range". */

0 commit comments

Comments
 (0)